2010-02-10 6 views
2

저는 Python C API에 조금 어려움을 겪고 있습니다. 파이썬 메서드를 호출하여 약 60hz에서 일부 게임 AI를 수행합니다. 그것은 의 시간을 보냈지 만 1 초마다 또는 그래서 PyEval_CallObject를 호출하면 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을 전역으로 저장하면 약 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

언제든지 PyImport_Import()으로 전화 할 수 있지만 동일한 모듈 개체를 계속 가져올 수 있습니다. 파이썬은 임포트를 캐시합니다. 또한 새로운 파이썬 문자열을 생성하고 참조 (따라서 객체)를 누출하는 대신 PyImport_ImportModule()을 사용하면됩니다. const char *이 필요합니다.

PyImport_Import*() 새로운 참조를 반환하지만 완료되면 Py_DECREF()으로 전화해야합니다. 모듈을 전역에 저장하는 것은 문제가되지 않아야합니다. 여기에서 참조하십시오.

PyEval_CallObject()으로 전화 할 때 Py_BuildValue()의 오류를 확인하지 않으면, 작업을 완료하면 Py_DECREF()으로 전화하지 않으므로 해당 객체도 유출됩니다.

실제 오류 처리에 이르기까지

를 (예외를 테스트하고 명심)는 C의 두 배에 파이썬 부동 소수점으로 변환하기 위해, 당신은 아마 대신 PyArg_Parse()에 대한 일 처리의 PyFloat_AsDouble()를 호출해야합니다 : PyErr_ExceptionMatches()를 예외가 무언가와 일치하는지 실제로 테스트하려고 할 때만 유용합니다. 예외가 발생했는지 알고 싶거나 실제 예외 객체를 얻으려면 PyErr_Occurred()을 호출해야합니다. 현재 예외 (실제 예외 객체 아님)을 빌린 참조로 반환하고, 아무것도 설정하지 않으면 NULL을 반환합니다. 트레이스 백을 stderr로 출력하고 싶다면, PyErr_Print()PyErr_Clear()을 사용하십시오. 코드에서 실제 오류를 더 자세히 검사하려면 PyErr_Fetch()이 현재 예외 객체와 이에 연결된 추적을 가져옵니다 (파이썬 코드에서 sys.exc_info()과 동일한 정보를 얻습니다). C 코드의 예외 처리에 깊이 관여합니다.

+0

+1 감사합니다 ... Py_BuildValue에 대한 호출을 인라인하면 누수 된 참조가 처리되지만 아마도 그렇지 않을 것이라고 생각했습니다.내가 PyErr_Fetch이 pyErr_Occurred –

+0

아아 날을주는 것을 볼 수 있습니다 는, C는 이런 경우를 디버깅 특히,() : PyErr_Print 수집 된 쓰레기없는 인쇄 예외 매우 편리합니다. –

+0

.NET 용으로 너무 많은 시간이 필요합니다. 좋아 이상한. 내 파이썬 스크립트 (콘솔로 출력 ... 내가는 Win32에있어) "('중량', 'CONOUT의 $') sys.stdout = 열기"를 추가하고 모든 작업 마술을 시작했다. 기괴한. –

관련 문제