2010-06-07 3 views
2

일부 I/O 작업 (파일, 표준 출력)을 한 번에 수행하는 클래스의 Python 메소드를 호출하는 C++ 클래스를 작성하려고합니다. 내가 겪었던 문제는 클래스가 다른 스레드에서 호출된다는 것입니다 : 때때로 메인 스레드, 때로는 다른 스레드. 분명히 다중 스레드 네이티브 응용 프로그램에서 파이썬 호출에 대한 접근 방식을 적용하려고했습니다. 기본적으로 모든 것은 PyEval_AcquireLock과 PyEval_ReleaseLock 또는 전역 잠금에서부터 시작됩니다. 문서 here에 따르면 스레드가 이미 잠겨있을 때 교착 상태가 발생합니다. 내 수업이 주 스레드 또는 Python 실행을 차단하는 다른 스레드에서 호출 될 때 교착 상태가 발생합니다.C++ app의 Python C API - 잠글 때 알아보기

파이썬> Cfunc1() - "내 수업", 그것은 PyEval_AcquireLock에 붙어 의 호출로 이어질 내부적으로 쓰레드를 생성 C++ FUNC은 분명히 파이썬은 이미 완료 C++ Cfunc1의 전화를 기다리고 즉, 잠겨 ... 이러한 잠금을 생략하면 정상적으로 완료됩니다. 또한 파이썬 인터프리터가 다음 사용자 명령에 대한 준비가되었을 때, 즉 스레드가 백그라운드에서 func을 호출 할 때 (기본 호출의 내부가 아닌) 완료되면

해결 방법을 찾고 있습니다. 전역 잠금이 허용되는지 여부를 구별해야합니다. 즉, Python이 잠겨 있지 않고 다음 명령을받을 준비가되지 않았는지 ... PyGIL_Ensure를 시도했지만, 불행히도 정지가 발생했습니다.

알려진 API 또는 해결 방법은 무엇입니까?

(파이썬 2.4) 당신은 매우 개인적으로 당신의 C++ 코드를 포장하지 않는 한

+0

메인 스레드에서 처리되는 메시지를 보내는 메시지 펌프가 있습니까? – kibibu

+0

스레드가 생성되는 방법을 명확히 할 수 있습니까? 그들은 Python API를 통해 생성됩니까? –

답변

2

, 어떤 파이썬 스레드 ++ 코드를 당신의 C를 호출 할 때 GIL은 를 개최했다. 을 C++ 코드로 배포 할 수 있습니다 (Python 상호 작용이 필요없는 일부 작업을 수행하려는 경우). 그러면 Python 상호 작용을 수행 할 때 코드를 다시 얻어야합니다 (the docs 참조). 당신은 그냥 좋은 오래된 C API를 사용하는 경우, 거기에 대한 매크로이며, 권장 관용구는 문서를 설명

Py_BEGIN_ALLOW_THREADS 
...Do some blocking I/O operation... 
Py_END_ALLOW_THREADS 

입니다 :

Py_BEGIN_ALLOW_THREADS 매크로는 새로운 블록을 열리고 선언 숨겨진 로컬 변수; Py_END_ALLOW_THREADS 매크로는 블록을 닫습니다. 두 가지 매크로를 사용하는 또 다른 이점은 파이썬 이 스레드 지원없이 컴파일 될 때 이 비어있는 것으로 정의되므로 스레드 상태와 GIL 조작을 저장한다는 것입니다.

그래서 당신은 단지 GIL을 취득 할 필요가 없습니다 (그리고해야되지 않음) 명시 적으로 (이상적으로 그 매크로)를 출시 한 후까지 다시 어떤 방식으로 파이썬과 상호 작용해야합니다. (문서가 "I/O 작업을 일부 차단하는"경우 실제로는 Python 상호 작용이없는 장기 실행 작업이 될 수 있습니다.)

+0

마침내 내가 찾던 대안을 찾았습니다.(_PyThreadState_Current == NULL) { 상태 = PyGILState_Ensure() } ... PyGILState_Release (상태) 내가 파이썬에서 스레드를 등록 할 필요 , 잘 작동하는 것 같다. 현재 수정 사항 테스트 중 ... – Alex