2009-09-26 7 views
8

Je travaille sur l'intégration de python dans C++. Dans un cas particulier, j'ai besoin de deux instances séparées de l'interpréteur dans le même fil. Puis-je placer l'interpréteur Python dans une classe C++ et obtenir des services de deux instances de classe ou plus?Interprète Python en tant que classe C++

Répondre

14

Je l'ai utilisé Py_NewInterpreter pour différents interprètes dans différents threads, mais cela devrait également travailler pour plusieurs interprètes au sein d'un fil:

Dans le thread principal:

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

Pour chaque instance interprète (dans n'importe quel 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 

Notez que vous avez besoin d'une variable myThreadState pour chaque interpréteur exemple!

Enfin la finition dans le thread principal:

PyEval_RestoreThread(mainThreadState); 
Py_Finalize(); 

Il y a quelques restrictions à l'utilisation de plusieurs instances d'interpréteur (ils ne semblent pas être totalement indépendant), mais dans la plupart des cas, cela ne semble pas causer des problèmes.

4

Vous pouvez, mais je vous recommande de ne pas ré-implémenter un interpréteur Python lorsqu'il existe une implémentation standard. Utilisez boost :: python pour interfacer avec Python.

+0

boost python utilise python capis. est-il possible de démarrer l'interpréteur deux fois en appelant Py_Initialize()? –

6

Callin Py_Initialize() deux fois ne fonctionnera pas bien, mais Py_NewInterpreter peut fonctionner, selon ce que vous essayez de faire. Lisez attentivement les docs, vous devez tenir le GIL quand vous appelez ceci.

+0

Je suppose que je ne vais pas obtenir une réponse directe à ma question. Votre réponse m'a donné quelques informations sur lesquelles je peux commencer à travailler. Py_NewInterpreter semble être la bonne option pour commencer à explorer le scénario que j'ai décrit. Sur cette base, j'accepte votre réponse. –

1

Je ne pense pas que vous soyez la première personne à vouloir faire cela, malheureusement je crois que ce n'est pas possible. Êtes-vous capable d'exécuter les interperters python en tant que processus distincts et d'utiliser RPC?

0
  • Vous pouvez laisser l'interpréteur Python vivre en dehors de l'espace mémoire de votre application. Il suffit d'intégrer l'interpréteur dans une DLL.
  • Vous pouvez configurer & enregistrer des contextes python pour simuler deux interpréteurs différents.
1

La réponse de mosaik n'a pas fonctionné dans ma situation où mon module est un plugin à une application hôte qui initialise déjà python. J'ai réussi à le faire fonctionner avec le code suivant.

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

Quand j'ai appelé PyEval_AcquireLock() le programme bloqué et la fonction ne sont pas revenus. En outre, l'appel PyEval_ReleaseThread(myState) a semblé invalider l'interpréteur également.