c++ - 如何使用 Python C/API 包装多线程 C++ 库?

标签 c++ python pthreads

这是一个有点长的问题,但我希望我能表达清楚。

我正在尝试使用 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 回溯显示

Program received signal SIGSEGV, Segmentation fault.

__pthread_mutex_lock (mutex=0x0) at 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 如何与 pthreads 一起玩的权威文档?

最佳答案

从你的描述来看,这听起来根本不像是线程问题:你声称你定义了 Dummy 类而不使用 Python API,但这意味着 Dummy 实例不是 PyObjects,所以 reinterpret_cast 会做错事。您不能仅通过实例化 C++ 类来创建 PyObjects;您需要使用 Python 的对象系统并创建适当的 PyType 结构和 PyObject 结构并正确初始化两者。您还需要确保您的 refcounts 是正确的。

一旦你完成排序,关于线程要记住的主要事情是任何接触 Python 对象或使用任何 Python API 的调用(除了获取 GIL 的函数)必须获得 GIL。如果您的 C++ 库中的任何线程试图回调 Python 代码或接触 Python 对象,则访问需要包装在 PyGILState_Ensure/PyGILState_Release 中。

关于c++ - 如何使用 Python C/API 包装多线程 C++ 库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5416368/

相关文章:

c++ - 对大数进行加法运算

python - 使用带有 key 的 github

c - pthread执行陷入无限循环

c - 系统函数调用时出现段错误

c++ - 智能指针与哑指针 : polymorphism behavior oddity

c++ - cout 一个带有类定义的变量

c++ - C++ 如何从子类向父类(super class)添加方法

python - 使用 python_speech_features 获取 96 个 MFCC 特性

python - PyQT5为什么get请求响应总是为null

c - 如何在不强制使用 c 的情况下为每个线程分配任务,即每个线程在完成第一项工作后需要执行一些工作?