从C++调用Python

7
我正在尝试从我的主C++程序中调用Python脚本中的函数。 Python函数将字符串作为参数并返回无(好的.. 'None')。只要之前的调用在再次调用该函数之前完成,它就可以完美地工作(从未想过会那么容易...),否则会在pModule = PyImport_Import(pName)处发生访问冲突。
有很多关于如何在C和Python之间嵌入的教程,但我没有找到任何有关这个问题的内容。
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
当你说“只要在函数再次调用之前完成了上一次调用”,我只能假设你有多个线程从C++调用Python。Python不是线程安全的,所以这将失败!
请阅读Python手册中的全局解释器锁(GIL)。也许以下链接会有所帮助:

在维基百科上提到了GIL:


1

感谢您的帮助!

是的,您说得对,有几个C线程。我从来没有想过需要为解释器本身使用互斥锁——GIL对我来说是一个全新的概念(在整个教程中甚至没有提到一次)。

阅读参考文献后(虽然这肯定不是最容易的部分,但PyGILState_*函数大大简化了整个过程),我添加了一个

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

用于正确初始化解释器的函数。每个线程都创建自己的数据结构,获取锁定并在参考文献中显示后释放它。

它按预期工作,但在终止进程之前调用Py_Finalize()时会导致段错误..是否有问题就这样离开它?


2
我很高兴这解决了你的问题。我不知道为什么你调用Py_Finalize()会出现问题 - 也许你可以提供一个简化的示例,在另一个问题中展示出该问题。你真的应该干净地关闭Python,但如果你只是要退出应用程序,那就没问题了...... 我强烈建议你找出它崩溃的原因。 - Daniel Paull
@DanielPaull,您能否提供一个简单的工作示例来说明上述主题?这样我就可以更容易地理解了。 - lkkkk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接