Question

Je travaille sur l'intégration de python pour c ++. Dans certains cas particulier, je requiers deux instances distinctes de l'interprète en même thread.

Puis-je envelopper interpréteur Python dans un c ++ classe et obtenir des services de deux ou plusieurs instances de classe?

Était-ce utile?

La solution

Je l'ai utilisé Py_NewInterpreter pour différents interprètes dans des threads différents, 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 de l'interpréteur (en tout fil):

// 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 myThreadState variable pour chaque instance interprète!

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.

Autres conseils

Callin Py_Initialize() ne fonctionne pas bien deux fois, mais Py_NewInterpreter peut travailler, en fonction de ce que vous essayez de faire. Lisez attentivement la documentation, vous devez tenir le GIL lorsque vous appelez.

Vous pouvez, mais je vous recommande de ne pas ré-implémenter un interpréteur Python quand il y a une implémentation standard. Utilisez boost :: python pour l'interface avec Python.

Je ne pense pas que vous êtes la première personne à vouloir le faire, je crois, malheureusement, il est impossible. Êtes-vous en mesure d'exécuter les interperters python comme des processus séparés et utiliser RPC?

La réponse de Mosaik ne fonctionnait pas dans ma situation où mon module est un plugin pour une application hôte qui initialise déjà python. J'ai pu 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 revenait pas. En outre, appelant PyEval_ReleaseThread(myState) semblait invalider l'interprète également.

  • Vous pouvez laisser l'interpréteur python en direct en dehors de votre espace de mémoire d'application. Il suffit de l'intégrer interprète dans une DLL.
  • Vous pouvez configurer et enregistrer des contextes de python pour simuler deux interprètes différents.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top