我奋力有点使用Python C API。我打电话蟒蛇方法做一些游戏AI在大约60赫兹。它的工作原理的时间,但在一个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()当你用它做,所以你泄露该对象也是如此。

为了给一个Python浮点转换为C双键的,你应该只调用PyFloat_AsDouble(),而不是摆弄PyArg_Parse()(并牢记测试例外)

下到实际的错误处理:当你真正想要测试是否异常匹配的东西PyErr_ExceptionMatches()才有用。如果你想知道,如果发生异常,或者获得实际的异常对象,PyErr_Occurred()是你应该叫什么。它返回当前异常(不是实际的异常对象),为借用参考,或NULL,如果没有设置。如果你只想打印一个回溯到stderr,PyErr_Print()PyErr_Clear()是要使用什么。对于你的代码中的实际错误的更细粒度的检查,PyErr_Fetch()让你与它(它可以让你在相同的信息Python代码sys.exc_info())。所有的事情考虑,你很少想获取有关当前异常对象和追踪深地进入异常在C代码处理。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top