使用pybind11将Python解释器嵌入到多线程C ++程序中

巴瓦扎

我试图使用pybind11来使第三方C ++库调用Python方法。该库是多线程的,每个线程创建一个Python对象,然后对该对象的方法进行大量调用。

我的问题是py::gil_scoped_acquire acquire;死锁的调用下面给出了重现该问题的最少代码。我究竟做错了什么?

// main.cpp
class Wrapper
{
public:
  Wrapper()
  {
    py::gil_scoped_acquire acquire;
    auto obj = py::module::import("main").attr("PythonClass")();
    _get_x = obj.attr("get_x");
    _set_x = obj.attr("set_x");
  }
  
  int get_x() 
  {
    py::gil_scoped_acquire acquire;
    return _get_x().cast<int>();
  }

  void set_x(int x)
  {
    py::gil_scoped_acquire acquire;
    _set_x(x);
  }

private:
  py::object _get_x;
  py::object _set_x;
};


void thread_func()
{
  Wrapper w;

  for (int i = 0; i < 10; i++)
  {
    w.set_x(i);
    std::cout << "thread: " << std::this_thread::get_id() << " w.get_x(): " << w.get_x() << std::endl;
    std::this_thread::sleep_for(100ms);    
  }
}

int main() {
  py::scoped_interpreter python;
  
  std::vector<std::thread> threads;

  for (int i = 0; i < 5; ++i)
    threads.push_back(std::thread(thread_func));

  for (auto& t : threads)
    t.join();

  return 0;
}

和Python代码:

// main.py
class PythonClass:
    def __init__(self):
        self._x = 0

    def get_x(self):
        return self._x

    def set_x(self, x):
        self._x = x

相关问题可以在此处此处找到,但并不能帮助我解决问题。

巴瓦扎

在启动辅助线程(已添加py::gil_scoped_release release;之前,我设法通过在主线程中释放GIL来解决了该问题对于任何有兴趣的人,现在可以使用以下方法(还添加了清理Python对象的功能):

#include <pybind11/embed.h>  
#include <iostream>
#include <thread>
#include <chrono>
#include <sstream>

namespace py = pybind11;
using namespace std::chrono_literals;

class Wrapper
{
public:
  Wrapper()
  {
    py::gil_scoped_acquire acquire;
    _obj = py::module::import("main").attr("PythonClass")();
    _get_x = _obj.attr("get_x");
    _set_x = _obj.attr("set_x");

  }
  
  ~Wrapper()
  {
    _get_x.release();
    _set_x.release();
  }

  int get_x() 
  {
    py::gil_scoped_acquire acquire;
    return _get_x().cast<int>();
  }

  void set_x(int x)
  {
    py::gil_scoped_acquire acquire;
    _set_x(x);
  }

private:
  py::object _obj;
  py::object _get_x;
  py::object _set_x;
};


void thread_func(int iteration)
{
  Wrapper w;

  for (int i = 0; i < 10; i++)
  {
    w.set_x(i);
    std::stringstream msg;
    msg << "iteration: " << iteration << " thread: " << std::this_thread::get_id() << " w.get_x(): " << w.get_x() << std::endl;
    std::cout << msg.str();
    std::this_thread::sleep_for(100ms);    
  }
}

int main() {
  py::scoped_interpreter python;
  py::gil_scoped_release release; // add this to release the GIL

  std::vector<std::thread> threads;
  
  for (int i = 0; i < 5; ++i)
    threads.push_back(std::thread(thread_func, 1));

  for (auto& t : threads)
    t.join();

  return 0;
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在pybind11中使用python中的C ++对象

使用 pybind11 在 python 中打印 C++ 类

pybind11:如何将c ++和python代码打包到一个包中?

如何在Pybind11中将Python dict转换为C ++计数器部分?

可以将Python解释器和Python应用程序源代码嵌入到已编译的程序中吗?

在C回调中如何使用Pybind11访问Python对象?

使用 pybind11 从 C++ 反序列化 Python 中的 protobuf 缓冲区

如何使用pybind11在C ++中调用python内置函数

使用 pybind11 在 C++ 中将 Python 类表示为 std::variant 中的类型

使用pybind11通过预先存在的嵌入式python解释器公开C ++功能

如何使用嵌入式python解释器构建和执行cpp文件(pybind11)

使用Pybind11将C ++扩展到Python

在C ++中访问pybind11 kwargs

在多线程应用程序中安全使用迭代器

如何使用pybind11从virtualenv运行python解释器?

如何中断C ++应用程序中嵌入的python解释器

多线程C程序中的随机函数

在C ++中,可以使用多线程工具将UNIX信号与主程序同步吗?

Java中这个多线程程序的代码输出怎么解释?

使用Java中的多线程将大量文件从本地复制到DBFS服务器

如何将共享指针列表传递给pybind11中的c ++对象

将Rust任务嵌入到C程序中?

将Powershell脚本嵌入到C#程序中

从C ++中的cppreference解释多线程示例

如何使用pybind11将Python函数作为C ++线程内的回调进行调用

通过pybind11遍历包装在Python中的C ++对象

Pybind11:将元组列表从Python传递到C ++

使用 PYBIND11_MODULE 时使用 Pybind11 将 C++ 函数集成到 Python 时出错

使用多线程将数据同时插入到列表中