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
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.
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.
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.
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. –
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?
- 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.
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.
boost python utilise python capis. est-il possible de démarrer l'interpréteur deux fois en appelant Py_Initialize()? –