2011-02-23 9 views
1

からPython関数を呼び出すしようとするとSegfault、私はいくつかの点でC.だから、C

からPythonのコールバック関数を呼び出したい、関数はCに送信され、この

ようタプルにパックされました
PyObject *userData = Py_BuildValue("Oi",py_callback,some_number); 

その地域のどこかに、Py_INCREF(py_callback)もあります。プログラム内のいくつかの後の時点で
は、私が

PyObject *py_callback; 
int some_number; 
PyArg_ParseTuple((PyObject*)userData,"Oi",&py_callback,&some_number); // returns true 
PyObject *py_result = PyObject_CallFunctionObjArgs(py_callback, 
                /* ... */ 
                NULL); 

と最後の呼び出しは、セグメンテーションフォールトをスローすることを、その関数を呼び出したいです。そんなことをやろうと思っているのですか?

+1

デバッグモードでコンパイルし、GDBにロードしてバックトレースを取得します。 –

+1

Pythonを呼び出す前にGILを保持していることを確認していますか? – ncoghlan

+0

私は別の問題を見つけました。それは、より多くの可能性の高い犯人です(私の答えを見てください)。それでも動作しない場合は、http://docs.python.org/dev/c-api/init.html#threadstate-and-the-global-interpreterlockを使用して、十分にGoogleの飼い主を探してくださいCPythonインタプリタロックを処理する方法の説明に従う方が簡単です。 – ncoghlan

答えて

5

のPythonのC APIから奇妙な振る舞いを取得し、それは常にあなたが正しくグローバルインタープリタロック(別名「GIL」)の状態を管理している価値がダブルチェックのとき:http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock

+0

ああ、すみません。それはタイプミスでした。私はそれに応じて問題を修正した。 – bastibe

+0

それでも意味をなさない - 'PyObject_CallFunctionArgs'の第2引数として何を渡していますか? '&some_number'は正しく動作しません(間違った型です)、現在のバージョンで' py_some_number'を初期化していません。あなたはPythonにコールバックしたいので、 '' OO "'を使い、その番号を '' PyObject''として保持しています。 – ncoghlan

+0

あなたはもちろんです。とにかく私はその番号を必要としないことを実際に考え出しました。 – bastibe

1

私はわからないんだけどなぜ誰もがここでGILについて話しているのです。あなたはどこにでもリリースしていますか?私は以下に挙げるいくつかの問題点に気付く。それは提案と混ざっている。

参照カウントをuserDataに増やしていないことがわかりました。何故なの?あなたはそれを保管していますか?なぜそれをタプルに格納したいのですか?なぜ、2つの変数(コールバックとデータ用)を保持し、参照を増やして参照を所有するのはなぜですか?

まず、すべての関数の戻り値がNULLかどうかを確認します。これにより、実際に正しく動作していることを確認できます。 PyObject_Printを使用して、コード内のすべての点で興味のあるオブジェクトを印刷して、期待通りに動作することを確認することをお勧めします。

segfaultがどこで発生したかについてのあなたのコメントから、PyObject_CallFunctionObjArgsでコールするときに間違った数のパラメータをコールバック関数に渡していると思います。それをもう一度確認できますか?コールバック関数の定義を表示し、呼び出しを再度確認してください。

私が見る別の可能性のある問題は、名前から、py_some_numberはPythonの整数オブジェクトを期待するように聞こえるということです。これはそうではありません。 PyArg_ParseTupleの後には、整数が入ります。

+0

Cコールバック関数はPortaudioによる関数定義に準拠しなければならないので、 'userData'は1つのポインタにしかなりません。私はすべての呼び出しと引数をチェックしてダブルチェックしたが、間違いない。しかし、refcountsを増やすことについてのヒントをありがとう! – bastibe

+1

私は好奇心が強いです。何が変わって問題が解決したのですか? –

+0

Pythonへの呼び出しの前に 'PyGILState_STATE gstate = PyGILState_Ensure();'を挿入してください。バックエンドは実際には新しいスレッドを作成していたので、スレッドの状態を事前に確認せずにPythonの関数を呼び出すことはできませんでした。これが意味をなさないかどうかはわかりません。私はまだ別の質問でスレッドのものと苦労しています。 – bastibe