2009-09-26 16 views
8

Pracuję nad osadzaniem pythona w C++. W jakimś osobliwym przypadku wymagam dwóch oddzielnych instancji interpretera w tym samym wątku.Interpreter Pythona jako klasa C++

Czy można zawinąć interpreter języka Python na klasę C++ i uzyskać usługi z dwóch lub więcej wystąpień klas?

Odpowiedz

14

I stosuje Py_NewInterpreter różnych tłumaczy w różne gwinty, ale również powinny działać na kilku tłumaczy ciągu nici:

W głównym gwintem:

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

W każdym przypadku interpretera (w dowolnym wątku):

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

Pamiętaj, że potrzebujesz zmiennej myThreadState dla każdego tłumacza instancja!

końcu wykończenie w głównym wątku:

PyEval_RestoreThread(mainThreadState); 
Py_Finalize(); 

Istnieją pewne ograniczenia w zastosowaniu kilku wystąpień tłumacza (wydają się nie być całkowicie niezależne), ale w większości przypadków to nie wydaje się być przyczyną problemów.

4

Możesz, ale nie polecam ponownego wdrożenia interpretera Pythona, gdy istnieje standardowa implementacja. Użyj boost :: python do interfejsu z Pythonem.

+0

Dodatkowy python używa python c apis. czy można uruchomić interpreter dwukrotnie, wywołując Py_Initialize()? –

6

Callin Py_Initialize() dwa razy nie zadziała dobrze, jednak Py_NewInterpreter może działać, w zależności od tego, co próbujesz zrobić. Przeczytaj uważnie dokumenty, musisz mieć GIL podczas wywoływania tego.

+0

Chyba nie dostanę prostej odpowiedzi na moje pytanie. Twoja odpowiedź dała mi pewne dane, na podstawie których mogę rozpocząć pracę. Py_NewInterpreter wydaje się być właściwą opcją rozpoczęcia eksploracji scenariusza, który opisałem. Na tej podstawie akceptuję twoją odpowiedź. –

1

Nie sądzę, że jesteś pierwszą osobą, która chce to zrobić, niestety uważam, że nie jest to możliwe. Czy potrafisz uruchamiać interpretery Pythona jako oddzielne procesy i używać RPC?

0
  • Możesz pozwolić interpreterowi Pythona na żywo poza obszarem pamięci aplikacji. Wystarczy osadzić interpretera w bibliotece DLL.
  • Można skonfigurować & zapisywanie kontekstów Pythona w celu symulacji dwóch różnych interpretatorów.
1

Odpowiedź mozaika nie działa w mojej sytuacji, w której mój moduł jest wtyczką do aplikacji hosta, która już inicjuje pythona. Udało mi się go uruchomić z następującym kodem.

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

Gdy zadzwoniłem PyEval_AcquireLock() program zablokowany, a funkcja nie wracał. Ponadto wywołanie PyEval_ReleaseThread(myState) wydawało się również unieważnić interpreter.