2011-02-23 4 views
1

그래서, 나는 C에서 파이썬 콜백 함수를 호출하고 싶다.C에서 파이썬 함수를 호출하려고 할 때 Segfault

어떤 시점에서, 함수는 C로 보내지고 다음과 같은 튜플로 압축된다.

PyObject *userData = Py_BuildValue("Oi",py_callback,some_number); 

그 영역의 어딘가에 Py_INCREF(py_callback) , 너무.
프로그램에서 나중에, 그 함수를 호출하고 싶습니다.

PyObject *py_callback; 
int some_number; 
PyArg_ParseTuple((PyObject*)userData,"Oi",&py_callback,&some_number); // returns true 
PyObject *py_result = PyObject_CallFunctionObjArgs(py_callback, 
                /* ... */ 
                NULL); 

마지막 호출이 세그먼트 화 오류를 발생시킵니다. 당신은 어떤 생각을 가지고 있습니까, 왜 그렇게 할 것입니까?

+1

디버그 모드로 컴파일하고, GDB에서로드하고 백 트레이스를 얻습니다. –

+1

파이썬을 다시 호출하기 전에 GIL을 잡고 있는지 확인 하시겠습니까? – ncoghlan

+0

나는 더 많은 가능성이있는 다른 문제를 발견했다 (내 대답 참조). 그래도 작동하지 않으면 http://docs.python.org/dev/c-api/init.html#thread-state-and-the-global-interpreterlock에서 볼 수있는 Google 사료를 충분히 제공해야합니다. CPython 인터프리터 잠금을 처리하는 방법에 대한 설명을 따라하기 쉽습니다. – ncoghlan

답변

5
파이썬 C API의 이상한 행동을 받고, 그것을 올바르게 글로벌 통역 잠금 (일명 "는 GIL")의 상태를 관리하는 가치를 두 번 검사 항상 때

: http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock

+0

오, 죄송합니다. 그것은 오타였습니다. 그에 따라 문제를 해결했습니다. – bastibe

+0

아직도 이해가되지 않습니다 - 두 번째 인자로'PyObject_CallFunctionArgs'를 어떻게 넘겨 줍니까? '& some_number'는 올바르게 작동하지 않습니다 (타입이 잘못되었습니다) 그리고 현재 버전에서는'py_some_number'를 전혀 초기화하지 않았습니다. 파이썬으로 다시 전화하기를 원할 때,''OO ''를 사용하고 숫자를''PyObject''로 유지하는 것은 여러분이하고 싶은 일입니다. – ncoghlan

+0

물론 맞습니다. 어쨌든 그 번호는 필요 없다는 것을 실제로 알아 냈습니다. – bastibe

1

는 잘 모르겠어요 왜 모두가 GIL에 대해 이야기하고 있는지. 어디에서나 풀어주고 있습니까? 나는 아래에 열거 될 몇 가지 가능한 문제점을 발견했다. 그것은 제안과 혼합되어 있습니다.

userData의 참조 카운트를 증가시키지 않고 있습니다. 왜 안돼? 당신은 당신이 아닌 당신을 저장하고 있습니까? 왜 그것을 튜플에 저장하고 싶습니까? 두 개의 변수 (콜백 및 데이터)를 유지 한 다음 참조를 소유 할 수 있도록 refcount를 증가시키는 것이 어떨까요?

우선 모든 함수의 반환 값이 NULL인지 확인하십시오. 이렇게하면 실제로 제대로 작동하는지 확인할 수 있습니다. PyObject_Print을 사용하여 코드의 모든 지점에서 관심있는 객체를 인쇄하여 원하는대로 진행되도록하는 것이 좋습니다.

segfault가 발생한 위치에 대한 귀하의 의견에서 PyObject_CallFunctionObjArgs으로 전화 할 때 콜백 함수에 잘못된 수의 매개 변수를 전달하고 있다고 생각합니다. 그것을 다시 확인할 수 있습니까? 어쩌면 콜백 함수 정의를 보여주고 호출을 다시 검사 할 수도 있습니다.

내가 볼 수있는 또 다른 가능한 문제는 이름에서부터 py_some_number은 Python 정수 객체를 기대하는 것 같습니다. 그렇지 않다. PyArg_ParseTuple 뒤에는 정수가 포함됩니다.

+0

C-callback 함수는 Portaudio의 함수 정의를 따라야하므로'userData'는 하나의 포인터 만 될 수 있습니다. 나는 모든 호출과 인자들을 체크하고 두 번 체크했다. 그리고 그것들은 틀림없이 정확하다. refcounts를 증가시키는 팁에 감사드립니다! – bastibe

+1

나는 그 때 흥미 롭다. 어떤 점에서 문제가 해결 되었습니까? –

+0

Python을 호출하기 전에'PyGILState_STATE gstate = PyGILState_Ensure();'를 삽입하십시오. 백엔드는 실제로 새로운 스레드를 생성하기 때문에 스레드 상태를 미리 확인하지 않고 파이썬 함수를 호출 할 수는 없습니다. 이것이 합리적인지 확실하지 않습니다. 나는 아직도 다른 질문에 실을 꿰기에 고투하고있다. – bastibe

관련 문제