从C++调用Python

7 投票
2 回答
5015 浏览
提问于 2025-04-15 14:17

我想在我的主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 个回答

1

谢谢你的帮助!

是的,你说得对,确实有几个C线程。我从没想过解释器本身也需要互斥锁——全局解释器锁(GIL)对我来说是个全新的概念(而且在整个教程中根本没有提到过)。

在阅读参考资料后(这绝对不是最简单的部分,尽管PyGILState_*函数让整个事情简单了很多),我添加了一个

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

函数来正确初始化解释器。每个线程都会创建自己的数据结构,获取锁,然后像参考资料中所示的那样释放锁。

这样做效果很好,但在进程结束前调用Py_Finalize()时,我遇到了段错误……如果不调用它会有什么问题吗?

5

当你说“只要上一个调用在函数再次被调用之前完成”,我只能猜测你是在说有多个线程从C++调用Python。Python本身并不是线程安全的,所以这样做会出问题!

你可以看看Python手册中的全局解释器锁(GIL)。也许下面的链接会对你有帮助:

维基百科上也提到了GIL:

撰写回答