简体   繁体   English

Python解释器作为c ++类

[英]Python interpreter as a c++ class

I am working on embedding python in to c++. 我正在努力将python嵌入到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? 我可以将Python解释器包装到c ++类中并从两个或更多类实例获取服务吗?

I have used Py_NewInterpreter for different interpreters in different threads, but this should also work for several interpreters within one thread: 我已经在不同的线程中使用Py_NewInterpreter用于不同的解释器,但是这也适用于一个线程中的几个解释器:

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! 请注意,每个解释器实例都需要一个变量myThreadState!

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. 使用几个解释器实例有一些限制(它们似乎不完全独立),但在大多数情况下,这似乎不会导致问题。

Callin Py_Initialize() twice won't work well, however Py_NewInterpreter can work, depending on what you're trying to do. Callin Py_Initialize()两次不能正常工作,但Py_NewInterpreter可以工作,具体取决于你想要做什么。 Read the docs carefully, you have to hold the GIL when calling this. 仔细阅读文档,调用它时必须持有GIL。

You can, but I'd recommend you not to re-implement a Python interpreter when there is a standard implementation. 您可以,但我建议您在有标准实现时不要重新实现Python解释器。 Use boost::python to interface with Python. 使用boost :: python与Python接口。

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? 您是否能够将python中间件作为单独的进程运行并使用RPC?

mosaik's answer did not work in my situation where my module is a plugin to a host application that already initializes python. mosaik的答案在我的情况下不起作用,我的模块是已经初始化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. 当我调用PyEval_AcquireLock() ,程序被阻止,函数没有返回。 Further, calling PyEval_ReleaseThread(myState) seemed to invalidate the interpreter also. 此外,调用PyEval_ReleaseThread(myState)似乎也使解释器无效。

  • You can let the python interpreter live outside of your application memory space. 您可以让python解释器位于应用程序内存空间之外。 Just embed the interpreter in a DLL. 只需将解释器嵌入DLL中即可。
  • You can set up & save python contexts to simulate two different interpreters. 您可以设置和保存python上下文来模拟两个不同的解释器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM