从 C++ 调用 Python
Posted
技术标签:
【中文标题】从 C++ 调用 Python【英文标题】:Call Python from C++ 【发布时间】:2009-09-13 11:04:48 【问题描述】:我正在尝试从我的主 C++ 程序调用 Python 脚本中的函数。 python 函数接受一个字符串作为参数并且不返回任何内容(ok.. '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;
【问题讨论】:
【参考方案1】:当您说“只要在再次调用函数之前完成上一次调用”时,我只能假设您有多个线程从 C++ 调用到 Python。 python不是线程安全的,所以这会失败!
阅读 Python 手册中的全局解释器锁 (GIL)。也许以下链接会有所帮助:
http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock http://docs.python.org/c-api/init.html#PyEval_InitThreads http://docs.python.org/c-api/init.html#PyEval_AcquireLock http://docs.python.org/c-api/init.html#PyEval_ReleaseLock***上提到了 GIL:
http://en.wikipedia.org/wiki/Global_Interpreter_Lock【讨论】:
【参考方案2】:感谢您的帮助!
是的,你是对的,有几个 C 线程。从没想过解释器本身需要互斥锁 - GIL 对我来说是一个全新的概念(甚至在整个教程中都没有提到)。
在阅读参考资料后(肯定不是其中最简单的部分,虽然 PyGILState_* 函数大大简化了整个事情),我添加了一个
void initPython()
PyEval_InitThreads();
Py_Initialize();
PyEval_ReleaseLock();
函数来正确初始化解释器。 每个线程都创建自己的数据结构,获取锁并在之后释放它,如参考中所示。
正常工作,但是在终止进程之前调用 Py_Finalize() 时,我得到一个段错误.. 离开它有什么问题吗?
【讨论】:
很高兴这解决了您的问题。我想不出为什么你会在调用 Py_Finalize() 时遇到问题——也许你可以提供一个简化的例子来显示另一个问题中的问题。你真的应该彻底关闭 Python,但如果你只是要退出应用程序,你可能会没事......我强烈建议你找出它崩溃的原因。 @DanielPaull 能否为上述相同主题提供一个简单的工作示例。所以我很容易理解以上是关于从 C++ 调用 Python的主要内容,如果未能解决你的问题,请参考以下文章