سؤال

أنا تكافح قليلا مع بيثون ج واجهة برمجة التطبيقات. أنا أدعو طريقة بيثون للقيام ببعض اللعبة AI في حوالي 60 هرتز. إنها تعمل عظم من الوقت ولكن كل ثانية أو نحو ذلك الدعوة إلى 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() غالبا ما تريد، ولكن عليك فقط الاستمرار في الحصول على نفس كائن الوحدة النمطية مرة أخرى. بايثون تخزين واردات. أيضا، بدلا من إنشاء سلسلة بيثون جديدة وتسريب المرجع (وبالتالي الكائن)، يجب عليك فقط استخدام PyImport_ImportModule(), ، الذي يأخذ const char *.

PyImport_Import*() إرجاع مرجع جديد، على الرغم من أنه يجب عليك الاتصال Py_DECREF() على ذلك عند الانتهاء. لا ينبغي أن تكون تخزين الوحدة النمطية في عالمي مشكلة، طالما كنت تملك إشارة إليها (والتي تقوم بها هنا.)

في مكالمتك إلى PyEval_CallObject() أنت لا تتحقق من نتيجة Py_BuildValue() للحصول على أخطاء، وأنت أيضا لا تتصل Py_DECREF() عندما تنتهي من ذلك، فأنت تسريب هذا الكائن أيضا.

من أجل تحويل Python تعويم إلى D مزدوج، يجب عليك فقط الاتصال PyFloat_AsDouble() بدلا من mucking حول PyArg_Parse() (واتركها في الاعتبار الاختبار للاستثناءات)

أسفل إلى التعامل مع الأخطاء الفعلية: PyErr_ExceptionMatches() مفيد فقط عندما تريد فعلا اختبار ما إذا كان الاستثناء يطابق شيئا ما. إذا كنت تريد معرفة ما إذا حدث استثناء، أو احصل على كائن الاستثناء الفعلي، PyErr_Occurred() هو ما يجب أن تتصل به. إرجاع الاستثناء الحالي اكتب (ليس كائن الاستثناء الفعلي) كمرجع مستعار، أو لاغيا إذا لم يتم تعيين أي شيء. إذا كنت ترغب في طباعة Traceback فقط إلى Stderr، PyErr_Print() و PyErr_Clear() هي ما تريد استخدامه. للحصول على تفتيش أكثر غرامة من الخطأ الفعلي في التعليمات البرمجية الخاصة بك، PyErr_Fetch() يحصل لك كائن الاستثناء الحالي و Traceback المرتبط به (يجعلك نفس المعلومات sys.exc_info() في كود بيثون.) كل الأشياء التي تعتبر نادرا ما ترغب في الحصول على ذلك بعمق في التعامل مع الاستثناء في رمز C.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top