Вызов Python из C ++ - PullRequest
       23

Вызов Python из C ++

7 голосов
/ 13 сентября 2009

Я пытаюсь вызвать функцию в скрипте Python из моей основной программы на C ++. Функция python принимает строку в качестве аргумента и ничего не возвращает (хорошо .. «Нет»). Он работает идеально (никогда не думал, что это будет так просто ...), если предыдущий вызов завершен до повторного вызова функции, в противном случае происходит нарушение доступа на pModule = PyImport_Import(pName).

Существует множество руководств по встраиванию python в C и наоборот, но я ничего не нашел об этой проблеме.

int callPython(TCHAR* title){
    PyObject *pName, *pModule, *pFunc;
    PyObject *pArgs, *pValue;

Py_Initialize();
    pName = PyUnicode_FromString("Main");
    /* Name of Pythonfile */

    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

if (pModule != NULL) {
        pFunc = PyObject_GetAttrString(pModule, "writeLyricToFile");
        /* function name. pFunc is a new reference */
        if (pFunc && PyCallable_Check(pFunc)) {
            pArgs = PyTuple_New(1);

    pValue = PyUnicode_FromWideChar(title, -1);

    if (!pValue) {
        Py_DECREF(pArgs);
                Py_DECREF(pModule);
        showErrorBox(_T("pValue is false"));
        return 1;
            }
    PyTuple_SetItem(pArgs, 0, pValue);

            pValue = PyObject_CallObject(pFunc, pArgs);
            Py_DECREF(pArgs);

            if (pValue != NULL) {
                //worked as it should!
                Py_DECREF(pValue);
            }
            else {
                Py_DECREF(pFunc);
                Py_DECREF(pModule);
                PyErr_Print();
        showErrorBox(_T("pValue is null"));
        return 1;
            }
        }
        else {
            if (PyErr_Occurred()) PyErr_Print();
            showErrorBox(_T("pFunc null or not callable"));
        return 1;
        }
        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    }
    else {
        PyErr_Print();
        showErrorBox(_T("pModule is null"));
    return 1;
    }
    Py_Finalize();
    return 0;
}

Ответы [ 2 ]

5 голосов
/ 13 сентября 2009

Когда вы говорите «до тех пор, пока предыдущий вызов завершен до повторного вызова функции», я могу только предположить, что у вас есть несколько потоков, вызывающих из C ++ в Python. Питон не является потокобезопасным, поэтому он потерпит неудачу!

Прочтите о Global Interpreter Lock (GIL) в руководстве по Python. Возможно, вам помогут следующие ссылки:

GIL упоминается в Википедии:

1 голос
/ 13 сентября 2009

Спасибо за вашу помощь!

Да, вы правы, есть несколько тем C. Никогда не думал, что мне понадобится мьютекс для самого интерпретатора - для меня GIL является совершенно новой концепцией (и даже ни разу не упомянутой во всем уроке).

После прочтения ссылки (наверняка, не самая простая ее часть, хотя функции PyGILState_ * все сильно упрощают), я добавил

void initPython(){
    PyEval_InitThreads();
    Py_Initialize();
    PyEval_ReleaseLock();
}

функция для правильной инициализации переводчика. Каждый поток создает свою структуру данных, получает блокировку и впоследствии снимает ее, как показано в ссылке.

Работает как надо, но при вызове Py_Finalize () перед завершением процесса я получаю segfault ... есть ли проблемы с его просто оставить?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...