私はpythonをc ++に埋め込むことに取り組んでいます。いくつかの特殊なケースでは、同じスレッドでインタープリターの 2 つの別個のインスタンスが必要です。
Python インタープリターを C++ クラスにラップして、2 つ以上のクラス インスタンスからサービスを取得できますか?
私はpythonをc ++に埋め込むことに取り組んでいます。いくつかの特殊なケースでは、同じスレッドでインタープリターの 2 つの別個のインスタンスが必要です。
Python インタープリターを C++ クラスにラップして、2 つ以上のクラス インスタンスからサービスを取得できますか?
異なるスレッドの異なるインタープリターに Py_NewInterpreter を使用しましたが、これは 1 つのスレッド内の複数のインタープリターでも機能するはずです。
メインスレッドで:
Py_Initialize();
PyEval_InitThreads();
mainThreadState = PyEval_SaveThread();
各インタープリター インスタンス (任意のスレッド内) について:
// 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
各インタープリターインスタンスに対して変数 myThreadState が必要であることに注意してください!
最後に、メイン スレッドの仕上げ:
PyEval_RestoreThread(mainThreadState);
Py_Finalize();
複数のインタプリタ インスタンスの使用にはいくつかの制限があります (それらは完全に独立していないようです) が、ほとんどの場合、これは問題を引き起こさないようです。
CallinPy_Initialize()
は2回うまく機能しませんPy_NewInterpreter
が、何をしようとしているかによっては機能する可能性があります。ドキュメントを注意深く読んでください。これを呼び出すときはGILを保持する必要があります。
可能ですが、標準の実装がある場合は、Pythonインタープリターを再実装しないことをお勧めします。boost::pythonを使用してPythonとインターフェースします。
mosaik の答えは、私のモジュールがすでに Python を初期化しているホスト アプリケーションへのプラグインであるという私の状況では機能しませんでした。次のコードで動作させることができました。
// 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)
PyEval_AcquireLock()
私がブロックされたプログラムを呼び出したとき、関数は戻りませんでした。さらに、呼び出しPyEval_ReleaseThread(myState)
はインタープリターも無効にしているように見えました。
あなたがこれをやりたいと思う最初の人ではないと思いますが、残念ながらそれは不可能だと思います。Pythonインターパーターを個別のプロセスとして実行し、RPCを使用できますか?