Python 解释器作为 c++ 类

Posted

技术标签:

【中文标题】Python 解释器作为 c++ 类【英文标题】:Python interpreter as a c++ class 【发布时间】:2010-12-01 14:48:27 【问题描述】:

我正在将 python 嵌入到 C++ 中。在某些特殊情况下,我需要在同一个线程中使用两个单独的解释器实例。

我可以将 Python 解释器包装到一个 c++ 类中并从两个或更多类实例中获取服务吗?

【问题讨论】:

【参考方案1】:

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) 似乎也使解释器无效。

【讨论】:

【参考方案2】:

我已经为不同线程中的不同解释器使用了 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();

使用多个解释器实例有一些限制(它们似乎不是完全独立的),但在大多数情况下,这似乎不会导致问题。

【讨论】:

【参考方案3】: 您可以让 python 解释器存在于您的应用程序内存空间之外。只需将解释器嵌入到 DLL 中即可。 您可以设置和保存 python 上下文来模拟两个不同的解释器。

【讨论】:

【参考方案4】:

我不认为你是第一个想要这样做的人,不幸的是我认为这是不可能的。您能否将 python 解释器作为单独的进程运行并使用 RPC?

【讨论】:

【参考方案5】:

调用Py_Initialize() 两次不会很好,但是Py_NewInterpreter 可以工作,这取决于你想要做什么。仔细阅读文档,调用时必须持有 GIL。

【讨论】:

我想我的问题不会得到直截了当的答案。你的回答给了我一些可以开始工作的投入。 Py_NewInterpreter 似乎是开始探索我所描述的场景的正确选择。基于此,我接受您的回答。【参考方案6】:

可以,但我建议您不要在有标准实现时重新实现 Python 解释器。使用 boost::python 与 Python 交互。

【讨论】:

boost python 使用 python c apis。是否可以通过调用 Py_Initialize() 来启动解释器两次?

以上是关于Python 解释器作为 c++ 类的主要内容,如果未能解决你的问题,请参考以下文章

python - C++ 嵌入式解释器和对象

Python类

怎么把python程序打包成操作系统?

从 C++ 嵌入式解释器捕获 python 窗口输出

Matplotlib 和 C++ 中嵌入式 python 的子解释器

在 C++ 中嵌入 Python:解释器在执行过程中的持久性