使用pybind11将Python成员函数添加到C++类

nxowjjhe  于 2023-06-07  发布在  Python
关注(0)|答案(1)|浏览(203)

使用pybind11,嵌入解释器并从C调用Python函数相对容易。但是,我不知道如何将Python成员函数添加到C类中。
到目前为止我所尝试的:

  • 创建一个C++类HelloWorld
  • 创建 Package 此类的PYBIND11_EMBEDDED_MODULE
  • 在Python模块中导入此模块,该模块将向HelloWorld添加成员函数
  • 将该模块导入HelloWorld本身

在C++方面,我有:

class HelloWorld
{
public:
  void run() const
  {
    py::scoped_interpreter guard{};

    auto backend = py::module_::import("backend");

    // TODO: call HelloWorld._run()
  }

  char const *msg() const
  { return "Hello, World!"; }
};

PYBIND11_EMBEDDED_MODULE(frontend, m)
{
  py::class_<HelloWorld>(m, "HelloWorld")
    .def_static("msg", &HelloWorld::msg);
}

在Python方面(backend.py

from frontend import HelloWorld

HelloWorld._run = lambda self: print(self.msg())

但是我现在如何从C调用HelloWorld._run呢?这个设置有意义吗?这个想法是用不同的Python后端扩展现有的C,这些后端可以快速组合在一起并在运行时交换。

dphi5xsq

dphi5xsq1#

传递@maxy的回调是一个很好的建议。你的原始代码结构可能在原则上是有意义的,但你试图向编译的C代码添加一个成员函数,这实际上并不起作用。这只能在运行时发生,并且是一种有效的方法,但不是作为成员函数。
观察者模式是一种设计模式,用于:https://sourcemaking.com/design_patterns/observer/cpp/3
通过这种方式,你可以维护一系列已经在Python中实现的回调(类似于添加成员函数),但随后从C
调用。本质上,你只是将函数指针传递给PyBind 11,所以有一个看起来像这样的绑定:

m.def("add_python_callback", [](HelloWorld& self, const py::function& callback) { self.addPythonCallback(callback); });

另一种方法是将Qt框架集成到您的解决方案中。https://www.qt.io/product/framework
Qt有一个“元对象编译器”,它允许你使用“信号”和“插槽”来实现观察者模式,而不需要上面描述的样板代码。你可以为QObject::connect创建一个绑定,然后将你的python定义的函数添加到你的C++类中。

相关问题