PyEval_CallObjectは時折ループに失敗します
-
19-09-2019 - |
質問
私は、PythonのC APIで少し苦労しています。私は約60HzにいくつかのゲームAIを行うにはPythonのメソッドを呼び出しています。それは時間のの最もの動作しますが、NULLの戻り値の毎秒ほどPyEval_CallObject結果への呼び出し。私が正しくエラーを検出し、ループを続行した場合、エラーが再び発生したところ、すべてが、うまく次回秒程度である。
私は参照カウントと間違って何かをやっている疑いがあるが、私はそれが何であるかを把握することはできません。
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を保存する場合、私は約秒後にハードクラッシュを取得します。
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
{
私はのためのテストを行わずに...どちらか、まだ例外を抽出する方法を見つけることができませんでした。のすべてのの例外
}
}
私はこの権利を行うにしても近いのでしょうか?私が言ったように、それは主に動作しますが、私は本当に私がエラーを取得しています理由を理解したいと思います。
すべての助けを事前にありがとうございます。
解決
あなたはできるだけ頻繁にあなたが好きなようPyImport_Import()
呼び出すことができますが、戻ったばかりの同じモジュールオブジェクトを取得しておこう。 Pythonは輸入をキャッシュします。また、代わりに新しいPythonの文字列を作成し、参照の漏洩(したがってオブジェクト)の、あなただけのPyImport_ImportModule()
を取るconst char *
を使用する必要があります。
PyImport_Import*()
が完了したら、しかし、あなたはそれにPy_DECREF()
を呼び出す必要があり、新しい参照を返します。グローバルにモジュールを保存する(ここでは、あなたがいる。)限り、あなたはそれへの参照を所有して、問題になることはありません。
PyEval_CallObject()
するあなたの呼び出しでは、エラーをPy_BuildValue()
の結果を確認していない、とあなたはそれを終えたら、あなたはまた、Py_DECREF()
を呼び出していないので、あなたにも、そのオブジェクトをリークしています。
ダブル、あなたはおそらくだけではなく、PyFloat_AsDouble()
で約いじくるのPyArg_Parse()
を呼び出し(例外をテストするために心に留めておく)必要がありますCにPythonの浮動小数点数を変換するために、
実際のエラー処理にダウン:あなたが実際に例外が何かにマッチするかどうかをテストしたいときPyErr_ExceptionMatches()
にのみ有効です。あなたは例外が発生した場合は知っている、または実際の例外オブジェクトを取得したい場合は、PyErr_Occurred()
はあなたが呼び出す必要がありますものです。何も設定されていない場合には、借用参照、またはNULLとして現在の例外型の(ない実際の例外オブジェクト)を返します。あなただけのstderrにトレースバックを印刷したい場合は、PyErr_Print()
とPyErr_Clear()
は、使用したいものです。あなたのコード内の実際のエラーのよりきめ細かい検査のために、PyErr_Fetch()
はあなたの現在の例外オブジェクトとそれに関連するトレースバックを取得します(それはあなたのPythonコードでsys.exc_info()
と同じ情報を取得します。)すべてのものは、あなたがめったにあることを取得したいんみなさ深くCコードで例外処理に