3

Python C API で少し苦労しています。約 60hz でゲーム AI を実行するために Python メソッドを呼び出しています。ほとんどの場合は機能しますが、1 秒おきに PyEval_CallObject を呼び出すと、戻り値が NULL になります。エラーを正しく検出してループを続行すると、次の 1 秒ほどは問題なく動作しますが、エラーが再び発生します。

私は参照カウントで何か間違ったことをしていると思いますが、それが何であるかわかりません:

int script_do_ai(struct game_data_t* gd)
{

    PyObject *pAiModule, *pResult;

    float result=0.0;
    pResult = NULL;

    pAiModule = PyImport_Import(PyString_FromString("ai_script"));

ええ、繰り返しごとにモジュールをインポートしています。それは必要ですか?pAiModule をグローバルとして保存すると、約 1 秒後にハード クラッシュが発生します。

    pResult = PyEval_CallObject(PyObject_GetAttrString(pAiModule, "do_ai"),
                               Py_BuildValue("f", gd->important_float))  
    if (pResult != NULL)
    {       
        PyArg_Parse(pResult, "f", &result);
        Py_DECREF(pResult);
        ConquerEnemies(result);  //you get the idea
    }
    else  //this happens every 75 or so iterations thru the loop
    {
       if (PyErr_ExceptionMatches(PyExc_SomeException))  //? not sure what to do here
       {

私はまだ例外を抽出する方法を見つけることができませんでした...すべての例外をテストすることなく

       }
    }

私はこれを正しく行うことに近づいていますか?私が言ったように、それはほとんど動作しますが、エラーが発生する理由を本当に理解したいです.

よろしくお願いします。

4

1 に答える 1

5

好きなだけ呼び出すことができPyImport_Import()ますが、同じモジュール オブジェクトを取得し続けるだけです。Python はインポートをキャッシュします。また、新しい Python 文字列を作成して参照 (したがってオブジェクト) をリークする代わりに、単に を使用する必要PyImport_ImportModule()がありconst char *ます。

PyImport_Import*()新しい参照を返しますが、完了したらそれを呼び出す必要がありPy_DECREF()ます。モジュールへの参照を所有している限り、モジュールをグローバルに格納することは問題になりません (ここではそうします)。

あなたへの呼び出しでは、エラーPyEval_CallObject()の結果をチェックしていません。また、完了時に呼び出しもしていないため、そのオブジェクトもリークしています。Py_BuildValue()Py_DECREF()

PyFloat_AsDouble()Python の float を C の double に変換するには、いじる代わりに単に呼び出す必要がありますPyArg_Parse()(例外をテストすることを忘れないでください) 。

実際のエラー処理に至るまで:PyErr_ExceptionMatches()例外が何かに一致するかどうかを実際にテストしたい場合にのみ役立ちます。例外が発生したかどうかを知りたい場合、または実際の例外オブジェクトを取得したい場合は、PyErr_Occurred()呼び出す必要があります。現在の例外タイプ(実際の例外オブジェクトではない) を借用参照として返すか、何も設定されていない場合は NULL を返します。トレースバックを stderr に出力するだけで、PyErr_Print()それPyErr_Clear()を使用したい場合。コード内の実際のエラーをより細かく検査するためにPyErr_Fetch()、現在の例外オブジェクトとそれに関連付けられているトレースバックを取得します ( sys.exc_info()Python コードと同じ情報を取得します)。 C コードでの例外処理。

于 2010-02-10T05:19:45.423 に答える