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

jin*_*eff 19 c++ python swig boost boost-python

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

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

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

这是可能的,如果是这样,怎么样?

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

我想这意味着我应该boost.Python用来包装我的图书馆?

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

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

更新

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

是)我有的:

我的Foo课程:

class Foo{...};
Run Code Online (Sandbox Code Playgroud)

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

import my_module
foo=my_modulde.Foo()
Run Code Online (Sandbox Code Playgroud)

我想要的是:

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

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;
}
Run Code Online (Sandbox Code Playgroud)

现在更清楚了吗?:)

Jam*_*mes 19

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

升压蟒蛇教程是一个良好的开端.


编辑:

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

#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\n"
            "\n"
            "def setup(a_foo_from_cxx):\n"
            "    print 'setup called with', a_foo_from_cxx\n"
            "    global a_foo\n"
            "    a_foo = a_foo_from_cxx\n"
            "\n"
            "def run():\n"
            "    a_foo.doSomething()\n"
            "\n"
            "print 'main module loaded'\n"
        );

        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;
}
Run Code Online (Sandbox Code Playgroud)


Bor*_*ein 5

供参考,这是使用pybind11可以实现的方法:

#include <iostream>
#include <pybind11/pybind11.h>
namespace py = pybind11;

// Define C++ class "Foo"
class Foo {
    std::string s_;
public:
    Foo(const std::string &s) : s_(s) {}
    void doSomething() { std::cout << s_ << std::endl; }
};
typedef std::shared_ptr<Foo> FooPtr;

// Define Python module "bar" and Python class "bar.Foo" wrapping the C++ class
PYBIND11_MODULE(bar, m) {
    py::class_<Foo, FooPtr>(m, "Foo")
        .def("doSomething", &Foo::doSomething);
}

int main(int argc, char **argv)
{
    // Create a C++ instance of Foo
    FooPtr foo = std::make_shared<Foo>("Hello, World!");

    // Initialize Python interpreter and import bar module
    PyImport_AppendInittab("bar", PyInit_bar);
    Py_Initialize();
    PyRun_SimpleString("import bar");

    // Make C++ instance accessible in Python as a variable named "foo"
    py::module main = py::module::import("__main__");
    main.attr("foo") = foo;

    // Run some Python code using foo
    PyRun_SimpleString("foo.doSomething()");

    // Finalize the Python interpreter
    Py_Finalize();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)