我正在将 python 嵌入到 C++ 中。在某些特殊情况下,我需要在同一个线程中使用两个单独的解释器实例。
我可以将 Python 解释器包装到 c++ 类中并从两个或多个类实例中获取服务吗?
我正在将 python 嵌入到 C++ 中。在某些特殊情况下,我需要在同一个线程中使用两个单独的解释器实例。
我可以将 Python 解释器包装到 c++ 类中并从两个或多个类实例中获取服务吗?
我已经将 Py_NewInterpreter 用于不同线程中的不同解释器,但这也适用于一个线程中的多个解释器:
在主线程中:
Py_Initialize();
PyEval_InitThreads();
mainThreadState = PyEval_SaveThread();
对于每个解释器实例(在任何线程中):
// initialize interpreter
PyEval_AcquireLock(); // get the GIL
myThreadState = Py_NewInterpreter();
... // call python code
PyEval_ReleaseThread(myThreadState); // swap out thread state + release the GIL
... // any other code
// continue with interpreter
PyEval_AcquireThread(myThreadState); // get GIL + swap in thread state
... // call python code
PyEval_ReleaseThread(myThreadState);
... // any other code
// finish with interpreter
PyEval_AcquireThread(myThreadState);
... // call python code
Py_EndInterpreter(myThreadState);
PyEval_ReleaseLock(); // release the GIL
请注意,每个解释器实例都需要一个变量 myThreadState!
最后在主线程中完成:
PyEval_RestoreThread(mainThreadState);
Py_Finalize();
使用多个解释器实例有一些限制(它们似乎不是完全独立的),但在大多数情况下,这似乎不会导致问题。
调用Py_Initialize()
两次不会很好,但是Py_NewInterpreter
可以工作,这取决于你想要做什么。仔细阅读文档,调用它时你必须持有 GIL。
你可以,但我建议你不要在有标准实现时重新实现 Python 解释器。使用boost::python与 Python 交互。
mosaik 的答案在我的模块是已经初始化 python 的主机应用程序的插件的情况下不起作用。我能够让它与以下代码一起工作。
// initialize interpreter
::PyEval_InitThreads();
::PyThreadState *mainThread = ::PyThreadState_Get();
myState = ::Py_NewInterpreter();
... // call python code
::PyThreadState_Swap(mainThread);
... // any other code
mainThread = ::PyThreadState_Swap(myState)
... // call python code
::PyThreadState_Swap(mainThread)
... // any other code
// finished with interpreter
mainThread = ::PyThreadState_Swap(myState)
::Py_EndInterpreter(myState);
::PyThreadState_Swap(mainThread)
当我调用PyEval_AcquireLock()
程序被阻塞并且函数没有返回时。此外,呼叫PyEval_ReleaseThread(myState)
似乎也使解释器无效。
我不认为你是第一个想要这样做的人,不幸的是我相信这是不可能的。您是否能够将 python 解释器作为单独的进程运行并使用 RPC?