簡體   English   中英

如何使用Python C / API包裝多線程C ++庫?

[英]How to wrap multithreaded C++ library using Python C/API?

這是一個有點長的問題,但我希望我能清楚地表達出來。

我正在嘗試使用Python / C API包裝C ++庫。 主庫(例如mylib )具有自己的對象系統(類似於另一種語言的解釋器),並通過Id唯一標識其環境中的每個對象。 它在其init()函數中創建多個線程,並在不同的線程上執行不同的操作(例如,在一個線程上創建對象並在另一個線程中解釋命令)。 現在,我嘗試將其分為兩個級別:

  1. 我用mylib中的對象的ID創建了一個Dummy類。 Dummy構造函數實際上在mylib中調用一個函數來創建一個新對象並存儲其ID。 Dummy類中的其他方法類似地在mylib中調用等效函數。 這不使用Python / C API。

  2. 我創建了mylibmodule.cpp ,它使用Python / C API提供了將從Python解釋器調用的功能。

    我在PyMODINIT_FUNC init_mylib()調用mylib的init()函數。

    我編寫如下函數:

     static PyObject * py_new_Dummy(PyObject* self, PyObject *args){ // ... process arguments return reinterpret_cast<PyObject*>(new Dummy); } 

請注意,Dummy構造函數會在mylib中調用在使用pthreads創建的線程上執行的函數。

我將其編譯為_mylib.so,我有一個mylib.py:

 import _mylib

 class MyClass(obj):

     def __init__(self, *args)

         self.__ptr = _mylib.py_new_Dummy()

現在到實際的問題:我可以在Python解釋器中導入mylib,但是只要我嘗試:

a = MyClass(some_args)

我遇到了細分錯誤。 gdb回溯顯示

程序收到信號SIGSEGV,分段故障。

__pthread_mutex_lock(mutex = 0x0)在pthread_mutex_lock.c:50

甚至更有趣的是,如果我禁用了在mylib代碼中生成多個線程(仍與pthreads鏈接),則可以創建MyClass實例,但是在退出Python解釋器時會遇到分段違規的情況。

Python文檔(http://docs.python.org/extending/)中的“ Thin Ice”部分沒有啟發我。 我想知道是否應該對mylibmodule.cpp中的所有Python C / API調用使用PyGILState_Ensure和PyGILState_Release。 還是應該是Py_BEGIN_ALLOW_THREADS和Py_END_ALLOW_THREADS?

有人可以幫忙嗎? 是否有關於Python如何與pthread配合使用的權威性文檔?

從您的描述來看,這聽起來根本不是一個線程問題:您聲稱自己在不使用Python API的情況下定義了Dummy類,但這意味着Dummy實例不是PyObjects ,因此reinterpret_cast會做錯事。 您不能僅通過實例化C ++類來創建PyObject。 您需要與Python的對象系統一起使用,並創建適當的PyType結構和PyObject結構,並正確地初始化兩者。 您還需要確保您的引用計數正確。

排序后,要記住的關於線程的主要事情是,任何接觸Python對象或使用任何Python API的調用(獲取GIL的函數除外)都必須獲取GIL 如果C ++庫中的任何線程嘗試回調Python代碼或觸摸Python對象,則需要將訪問包裝在PyGILState_Ensure / PyGILState_Release

謝謝托馬斯指出紅鯡魚。 問題出在C ++端的線程初始化中。 是的,它不需要任何GIL操作,因為沒有其他C ++線程在訪問Python C / API。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM