Python 解释器作为 c++班级

发布于 2024-08-06 01:48:40 字数 111 浏览 9 评论 0原文

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

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

I am working on embedding python in to c++. In some peculiar case I require two separate instances of the interpreter in same thread.

Can I wrap Python interpreter in to a c++ class and get services from two or more class instances?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

穿越时光隧道 2024-08-13 01:48:40

我已将 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();

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

I have used Py_NewInterpreter for different interpreters in different threads, but this should also work for several interpreters within one thread:

In the main thread:

Py_Initialize();
PyEval_InitThreads();
mainThreadState = PyEval_SaveThread();

For each interpreter instance (in any thread):

// 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

Note that you need a variable myThreadState for each interpreter instance!

Finally the finish in the main thread:

PyEval_RestoreThread(mainThreadState);
Py_Finalize();

There are some restrictions with using several interpreter instances (they seem not to be totally independent), but in most cases this does not seem to cause problems.

倾城花音 2024-08-13 01:48:40

调用 Py_Initialize() 两次效果不佳,但是 Py_NewInterpreter 可以工作,具体取决于您要执行的操作。仔细阅读文档,调用时必须持有 GIL。

Callin Py_Initialize() twice won't work well, however Py_NewInterpreter can work, depending on what you're trying to do. Read the docs carefully, you have to hold the GIL when calling this.

伴我心暖 2024-08-13 01:48:40

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

You can, but I'd recommend you not to re-implement a Python interpreter when there is a standard implementation. Use boost::python to interface with Python.

じ违心 2024-08-13 01:48:40

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

mosaik's answer did not work in my situation where my module is a plugin to a host application that already initializes python. I was able to get it to work with the following code.

// 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)

When I called PyEval_AcquireLock() the program blocked and the function did not return. Further, calling PyEval_ReleaseThread(myState) seemed to invalidate the interpreter also.

终难遇 2024-08-13 01:48:40

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

I don't think you are the first person to want to do this, unfortunately I believe it is not possible. Are you able to run the python interperters as separate processes and use RPC?

羁拥 2024-08-13 01:48:40
  • 您可以让 python 解释器位于应用程序内存空间之外。只需将解释器嵌入到 DLL 中即可。
  • 您可以设置&保存 python 上下文来模拟两个不同的解释器。
  • You can let the python interpreter live outside of your application memory space. Just embed the interpreter in a DLL.
  • You can set up & save python contexts to simulate two different interpreters.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文