将 C++ 类实例暴露给 Python 嵌入式解释器

2021-12-24 00:00:00 python swig c++ boost boost-python

我正在寻找一种将 C++ 类实例公开给 Python 嵌入式解释器的简单方法.

I am looking for a simple way to expose a C++ class instance to a python embedded interpreter.

  • 我有一个 C++ 库.这个库是包装好的(暂时使用 swig),我可以从 python 解释器中使用它
  • 我有一个 C++ 主程序,它从我的库中实例化了一个 Foo 类并嵌入了一个 python 解释器

我想将我的 C++ 世界实例 Foo 暴露给 python 世界(并被视为一个 Foo 类).

I would like to expose my C++ world instance of Foo to the python world (and seen as a Foo class).

这可能吗,如果可能,怎么办?

我认为这几乎就像在第一个答案中一样:boost::python::ptr 或PyInstance_新用法

I think it's almost like in the first answer of : boost::python::ptr or PyInstance_New usage

我想这意味着我应该使用 boost.Python 来包装我的库?

I guess this means I should use boost.Python to wrap my library?

我唯一的目标是在嵌入式 python 解释器中操作我的 C++ Foo 实例(不确定是否可以用以前的方法完成).

My only goal is to manipulate my C++ instance of Foo in the embedded python interpreter (not sure that it can be done with the previous method).

希望我清楚,谢谢你的帮助.

Hope I am clear, thanks for your help.

更新

感谢您的回答.事实上,我已经将我的 Foo 类暴露给了 python(使用 swig).

Thanks for your answers. In fact, I already have exposed my Foo class to python (with swig).

我有什么:

我的 Foo 类:

class Foo{...};

我的包装库(包括 Foo 类)暴露给 python: 所以我可以启动 python 解释器并执行如下操作:

my wrapped library (including the Foo class) exposed to python: so I can start the python interpreter and do something like this :

import my_module
foo=my_modulde.Foo()

我想要的:

有一个 C++ 主程序,它嵌入了一个 python 解释器并操作 C++ 世界变量.

Having a C++ main program which embeds a python interpreter and manipulates C++ world variables.

int main(int argc, char **argv)
{
    Foo  foo;   // instanciates foo

    Py_Initialize();

    Py_Main(argc, argv); // starts the python interpreter
                         // and manipulates THE foo instance in it

    Py_Finalize();

    return 0;
}

现在更清楚了吗?:)

推荐答案

Boost python 允许您以非常紧密集成的方式将 c++ 类公开给 python - 您甚至可以包装它们,以便您可以从 c++ 类派生 python 类,并将虚拟方法解析为 python 覆盖.

Boost python Allows you to expose c++ classes to python in a very tightly integrated way - you can even wrap them so that you can derive python classes from your c++ ones, and have virtual methods resolved to the python overrides.

boost python 教程 是一个很好的起点.

您可以创建一个 c++ 对象并将对它的引用传递给内部 python 解释器,如下所示:

You can create a c++ object and pass a reference to it to an internal python interpreter like this:

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/python.hpp>
#include <string>
#include <iostream>

namespace bp = boost::python;

struct Foo{
    Foo(){}
    Foo(std::string const& s) : m_string(s){}
    void doSomething() {
        std::cout << "Foo:" << m_string << std::endl;
    }
    std::string m_string;
};

typedef boost::shared_ptr<Foo> foo_ptr;

BOOST_PYTHON_MODULE(hello)
{
    bp::class_<Foo, foo_ptr>("Foo")
        .def("doSomething", &Foo::doSomething)
    ;
};

int main(int argc, char **argv)
{
    Py_Initialize();
    try {
        PyRun_SimpleString(
            "a_foo = None
"
            "
"
            "def setup(a_foo_from_cxx):
"
            "    print 'setup called with', a_foo_from_cxx
"
            "    global a_foo
"
            "    a_foo = a_foo_from_cxx
"
            "
"
            "def run():
"
            "    a_foo.doSomething()
"
            "
"
            "print 'main module loaded'
"
        );

        foo_ptr a_cxx_foo = boost::make_shared<Foo>("c++");

        inithello();
        bp::object main = bp::object(bp::handle<>(bp::borrowed(
            PyImport_AddModule("__main__")
        )));

        // pass the reference to a_cxx_foo into python:
        bp::object setup_func = main.attr("setup");
        setup_func(a_cxx_foo);

        // now run the python 'main' function
        bp::object run_func = main.attr("run");
        run_func();
    }
    catch (bp::error_already_set) {
        PyErr_Print();
    }

    Py_Finalize();

    return 0;
}

相关文章