2009-09-26 12 views
8

Estoy trabajando en la incrustación de python en C++. En algún caso peculiar, necesito dos instancias separadas del intérprete en el mismo hilo.Intérprete de Python como clase de C++

¿Puedo envolver el intérprete de Python en una clase de C++ y obtener servicios de dos o más instancias de clases?

Respuesta

14

he utilizado Py_NewInterpreter para diferentes intérpretes en diferentes hilos, pero esto también debería funcionar para varios intérpretes dentro de un hilo:

En el hilo principal:

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

Para cada instancia de intérprete (en cualquier hilo):

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

Tenga en cuenta que necesita una variable myThreadState para cada intérprete ¡ejemplo!

Finalmente la meta en el hilo principal:

PyEval_RestoreThread(mainThreadState); 
Py_Finalize(); 

Hay algunas restricciones en el uso de varios casos de interpretación (que parecen no ser totalmente independiente), pero en la mayoría de los casos esto no parece causar problemas.

4

Puede, pero le recomiendo que no vuelva a implementar un intérprete de Python cuando haya una implementación estándar. Use boost :: python para interactuar con Python.

+0

boost python usa python c apis. ¿es posible iniciar el intérprete dos veces llamando a Py_Initialize()? –

6

Llamar a Py_Initialize() dos veces no funcionará bien, sin embargo, Py_NewInterpreter puede funcionar, dependiendo de lo que esté tratando de hacer. Lea los documentos con cuidado, debe mantener el GIL cuando lo llame.

+0

Supongo que no obtendré una respuesta directa a mi pregunta. Su respuesta me ha dado algunas sugerencias sobre las cuales puedo comenzar a trabajar. Py_NewInterpreter parece ser la opción correcta para empezar a explorar el escenario que he descrito. En base a esto, estoy aceptando tu respuesta. –

1

No creo que sea la primera persona que quiera hacer esto, lamentablemente creo que no es posible. ¿Eres capaz de ejecutar los interperters python como procesos separados y usar RPC?

0
  • Puede dejar que el intérprete de python viva fuera del espacio de memoria de su aplicación. Solo inserte el intérprete en una DLL.
  • Puede configurar & guardar contextos de python para simular dos intérpretes diferentes.
1

La respuesta de mosaik no funcionó en mi situación en la que mi módulo es un complemento para una aplicación host que ya inicializa Python. Pude hacer que funcionara con el siguiente código.

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

Cuando me llamaron PyEval_AcquireLock() el programa bloqueado y la función no regresó. Además, llamar al PyEval_ReleaseThread(myState) parecía invalidar el intérprete también.

Cuestiones relacionadas