4

ブロッキング操作 (選択) を実行し、着信メッセージを処理する C 関数をラップしています。私の理解では、C 関数がブロックされる場合、他のスレッドの実行を許可しながらそれを呼び出す正しい方法は次のとおりです。

Py_BEGIN_ALLOW_THREADS                                                  
blocking_function();
Py_END_ALLOW_THREADS

ただし、この関数がパラメーターとしてコールバック ポインターを受け取ることがあります。このコールバックは、C 関数によって前処理された受信メッセージを処理する際に呼び出されます。このコールバックを を呼び出す関数にラップすることに成功PyEval_CallObject()し、Python コールバックを渡すことができました。

スレッドのサポートを追加しているので、同時にできるかどうか疑問に思っています:

  • このブロッキング操作を呼び出す前に GIL を解放してください。
  • このブロッキング操作で安全に Python インタープリターにコールバックします。

これは問題を引き起こしますか?もしそうなら、それを回避する方法はありますか?

ありがとう。

4

2 に答える 2

7

私はこれらの API 関数を数か月前に使用しましたが、私の記憶は少し曖昧ですが、このコードが問題を解決すると信じています。バージョン 2.x を想定しています (3.x は異なる場合があります):

PyGILState_STATE gstate;
gstate = PyGILState_Ensure();

/* Make your call to PyEval_CallObject() here (and any other PY API calls). */

PyGILState_Release(gstate);

(上記はPython C/API docsから引用)

これは基本的に Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS マクロの逆です。それらの中で GIL を解放しますが、PyGILState 関数内では GIL を取得します。

于 2011-03-01T19:26:26.900 に答える
1

グローバルを使用して の結果を保存し、PyEval_SaveThreadこれをコールバックで使用して を呼び出すと機能しますPyEval_RestoreThread。コールバックのコンテキスト ポインターを介してコード内のコールバックにこれをよりきれいに渡す方法を理解する必要があるだけです。

于 2011-03-01T19:24:18.067 に答える