Сбой Python при возврате значения карты C ++ - PullRequest
0 голосов
/ 26 июня 2018

Я пишу тест, чтобы сохранить данные в карте C ++. Я использую Python C-Api.
Добавление значений int и получение длины карты не проблема.
Но когда я получаю значение с карты и хочу вернуть его в Python, интерпретатор вылетает. Это мой код:

    //some includes 
    int VerboseLog = 99;
    typedef map<const char*, int> SessionKeeper;
    static SessionKeeper openSessions;

    static PyObject* getSession(PyObject* self, PyObject* args) {
        cout << "get" << endl;
        const char *key;

        if (!PyArg_ParseTuple(args, "z*", &key)) {
            PyErr_SetString(PyExc_Exception, "UUID konnte nicht ausgelesen werden");
            PyErr_PrintEx(1);
            return NULL;
        }

        int r = openSessions.at(key);
        return Py_BuildValue("i", r);
    }

    static PyObject *addSession(PyObject* self, PyObject* args) {
        cout << "Hello" << endl;
        const char  *key;
        int toAppend;

        if (!PyArg_ParseTuple(args, "si", &key, &toAppend)) {
            PyErr_SetString(PyExc_Exception, "Ein Parameter konnte nicht ausgelesen werden");
            PyErr_PrintEx(1);
            return NULL;
        }

        openSessions[key] = toAppend;
        cout << openSessions.size() << endl;
        cout << openSessions[key] << endl;
        Py_RETURN_NONE;
    }

    static PyObject* length(PyObject *self){
        cout << "length: ";
        int i = openSessions.size();
        return Py_BuildValue("i",i);
    }

    static PyMethodDef SessionKeeper_methods[] = {
        /*Note the third entry (METH_VARARGS). This is a flag telling the interpreter the calling convention
        to be used for the C function. It should normally always be METH_VARARGS or METH_VARARGS | METH_KEYWORDS;
        a value of 0 means that an obsolete variant of PyArg_ParseTuple() is used.*/
        { "length", (PyCFunction)length, METH_VARARGS, "return length of a Session" },
        { "addSession", (PyCFunction)addSession, METH_VARARGS, "add a Session." },
        { "getSession", (PyCFunction)getSession, METH_VARARGS, "get a Session" },
        { NULL }
    };

    static PyModuleDef sessionKeeperMod = {
        PyModuleDef_HEAD_INIT,
        u8"SessionKeeper",
        NULL,
        -1,
        SessionKeeper_methods
    };

    static PyModuleDef CpluplusModules_ModDef = {
        PyModuleDef_HEAD_INIT,
        u8"CPlusPlusMouldes",
        u8"Enthält alle Erweietrungen",
        -1,
        NULL, NULL, NULL, NULL, NULL
    };

    PyMODINIT_FUNC PyInit_CPlusPlusModules(void) {
            PyObject* m, *sessionMod;

            if (PyType_Ready(&TAModulType) < 0)
                return NULL;

            if (PyType_Ready(&DatabaseReader_Type) < 0)
                return NULL;

            if (!(sessionMod = PyModule_Create(&sessionKeeperMod))) {
                cout << "fail" << endl;
                return NULL;
            }

            m = PyModule_Create(&CpluplusModules_ModDef);
            if (m == NULL)
                return NULL;

            Py_INCREF(&TAModulType);
            Py_INCREF(&DatabaseReader_Type);

            PyModule_AddObject(m, "TAModul", (PyObject *)&TAModulType);
            PyModule_AddObject(m, "DBReader", (PyObject *)&DatabaseReader_Type);
            PyModule_AddObject(m, "SessionKeeper", sessionMod);

            return m;
    }

Другие модули (DBReader и TAModule) работают нормально. Цель состоит в том, чтобы обезопасить объекты PythonObject (содержащие объекты DbReader и объекты TAModul) на карте.

Но ответьте на мой вопрос, почему getSession аварийно завершает работу интерпретатора по возвращении? И почему функция длины работает нормально.

1 Ответ

0 голосов
/ 27 июня 2018

map<const char*,...> будет совпадать на основе адреса строки, а не содержимого . Поэтому вполне вероятно, что at завершится неудачно и выдаст исключение C ++ out_of_range.

Вы должны начать с переноса строки

int r = openSessions.at(key);

с блоком try {} catch, чтобы остановить исключение out_of_range, распространяющееся через интерпретатор Python (который не является C ++, поэтому не может его обработать).

Затем вы должны изменить карту, чтобы она соответствовала ключу в содержимом строки. Самый простой способ - использовать map<std::string,int>.

...