2012-03-05 62 views
4

我正在使用SWIG將第三方C++包集成到python應用程序中。該軟件包通過網絡連接到專有API並接收更新。整體流程是python實例化一個C++對象,調用它的函數來設置它,然後等待更新。SWIG C++ Python多態和多線程

我使用SWIG's directors feature實現了更新的回調機制,並且在從python或由python調用的C++函數進行測試時,它可以很好地工作。也就是說,我可以繼承Python中的C++類,從C++中調用它的虛函數並查看python代碼優先執行。

問題:
當我收到來自網絡,我得到了更新:當調用回調函數

The thread 'Win32 Thread' (0x1f78) has exited with code 0 (0x0). 
Unhandled exception at 0x1e0650cb in python.exe: 0xC0000005: Access violation writing location 0x0000000c. 

這異常是從python27.dll中拋出。
我懷疑是這樣的:我違反了GIL
AFAIU更新使用線程來自不同的線程和呼叫Python的代碼。

在這一點上,我不知所措。 SWIG的導向器功能僅限於在python中啓動的流程(即從python管理的線程)?
我如何繞過這個?我如何從C++誘導更新爲Python?甚至可以使用SWIG?
我應該使用完全不同的方法嗎?

我打開了在這個問題上有什麼建議?

+0

[這篇文章在SWIG郵件列表](http: //article.gmane.org/gmane.comp.programming.swig/5306/match=multi+threading+python)正好說明了這個問題,並要求在SWIG中修復它。我想這個問題自2004年以來一直沒有處理過 – Jonathan 2012-03-06 07:09:49

回答

2

如果你痛飲包裹的C++代碼調用回調函數的線程,那麼很可能沒有GIL問題 - 痛飲生成的代碼做不執行我見過的任何GIL管理,這意味着當Python代碼調用到您的C++代碼時,您在整個調用過程中保留GIL。然而,如果你的C++代碼將回調推遲到另一個線程,那麼你很可能違反了GIL。這很簡單:在調用回調之前,調用PyGILState_Ensure(),並在回調完成時調用PyGILState_Release。請參閱http://docs.python.org/c-api/init.html,「非Python創建的線程」一節。 (如果您在此處使用C++異常處理,則可能需要格外小心以確保您可以釋放GIL。)

如果您尚未查看堆棧跟蹤,則需要驗證NULL指針deref在你的代碼中並不是什麼愚蠢的事情。 (你可以使用VS/GDB/WinDBG連接到運行你的代碼的Python進程; Python的執行仍然是不可思議的,但你可以用這種方式跟蹤你的C++代碼。)

+0

我發現如果你使用SWIG導向器,那麼如果另一個線程/進程會觸發回調,你將需要自己鎖定GIL。 – AndyG 2016-10-14 18:39:08