python - boost::python:将 C++ 类暴露给嵌入在 C++ 应用程序中的 python 脚本

标签 python c++ boost boost-python

我在 C++ 应用程序中使用 boost::python 成功加载了一个 python 脚本文件并调用了一个函数。

在boost python中EmbeddingPython wiki 上有关于 how to load a python module 的提示.

namespace bp = boost::python;

bp::object import(const std::string& module, const std::string& path, bp::object& globals)
{
    bp::dict locals;
    locals["module_name"] = module;
    locals["path"]        = path;

    bp::exec("import imp\n"
             "new_module = imp.load_module(module_name, open(path), path, ('py', 'U', imp.PY_SOURCE))\n",
             globals,
             locals);

    return locals["new_module"];
}

我可以成功地使用它来导入 python 模块 (test.py)

int main()
{
    Py_Initialize();

    bp::object main    = bp::import("__main__");
    bp::object globals = main.attr("__dict__");
    bp::object module  = import("test", "test.py", globals);
    bp::object run     = module.attr("run");

    run();

    return 0;
}

使用 hello-world test.py 脚本运行上面的代码工作正常:

测试.py:

def run():
    print "hello world"

输出:

hello world

将 C++ 类暴露给 python:

但是,我现在想向该脚本公开一个 C++ 类。

struct Foo
{
    void f() {}
};

根据 boost::python 文档,我按如下方式公开此类:

BOOST_PYTHON_MODULE(FooModule)
{
    bp::class_<Foo>("Foo")
        .def("f", &Foo::f)
        ;
}

按照上面链接的 wiki 中的说明,我可以导入我的 FooModule,并将其存储在我的 globals 中:

PyImport_AppendInittab("FooModule", &initFooModule); 

...

bp::object Foo = bp::import("FooModule");
globals["Foo"] = Foo;

此导入是在导入我的 test.py 脚本之前完成的,并且此 globals 对象是传递给 bp 的对象::exec 导入我的脚本时(即:Foo 应该 位于 bp::exec 向我公开的全局字典中导入时的脚本)。

但是,由于某些原因,我的 Foo 模块对 test.py 不可见

问题:

如何将我的 Foo 类暴露给正在加载的 test.py python 脚本?


完整的工作示例:

测试.py:

def run():
    foo = Foo()
    foo.f()

main.cpp:

#include <iostream>
#include <boost/python.hpp>

namespace bp = boost::python;

bp::object import(const std::string& module, const std::string& path, bp::object& globals)
{
    bp::dict locals;
    locals["module_name"] = module;
    locals["path"]        = path;

    bp::exec("import imp\n"
             "new_module = imp.load_module(module_name, open(path), path, ('py', 'U', imp.PY_SOURCE))\n",
             globals,
             locals);
    return locals["new_module"];
}

struct Foo
{
    void f() {}
};

BOOST_PYTHON_MODULE(FooModule)
{
    bp::class_<Foo>("Foo")
        .def("f", &Foo::f)
        ;
}

int main()
try
{
    PyImport_AppendInittab("FooModule", &initFooModule);
    Py_Initialize();

    // get a handle to the globals dict    
    bp::object main = bp::import("__main__");
    bp::object globals = main.attr("__dict__");

    // import FooModule, and store it in the globals dict
    bp::object Foo = bp::import("FooModule");
    globals["Foo"] = Foo;

    // import the test script, passing the populated globals dict
    bp::object module = import("test", "test.py", globals);
    bp::object run = module.attr("run");

    // run the script
    run();

    return 0;
}
catch(const bp::error_already_set&)
{
    std::cerr << ">>> Error! Uncaught exception:\n";
    PyErr_Print();
    return 1;
}

输出:

>>> Error! Uncaught exception:
Traceback (most recent call last):
  File "test.py", line 2, in run
    foo = Foo()
NameError: global name 'Foo' is not defined

最佳答案

与其尝试从 C++ 端将 FooModule 注入(inject) Python 脚本,不如从 C++ 端使用 PyImport_AppendInittab 注册模块,然后 import 它来自 Python 端:

import FooModule

def run():
    foo = FooModule.Foo()
    foo.f()

关于python - boost::python:将 C++ 类暴露给嵌入在 C++ 应用程序中的 python 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41004393/

相关文章:

python和数据帧: group by week and calculate the sum and difference

c++ - 在C++中使用OpenCV时网络摄像头的FPS随机下降

c++ - Windows下C++代码同步API失败

C++ 矩阵转置。 boost uBLAS 和双*?

c++ - 在 win7-64 位中通过 mingw 使用 boost.python 编译一些代码

visual-studio-2010 - 错误 LNK1104 : cannot open file 'libboost_thread-vc100-mt-gd-1_55.lib'

python - 使用图像相似性度量进行图像搜索

python - 使用 npm package/python 脚本将 .3ds 文件转换为 .obj/collada/gltf

python - 将列表中的相似词典合并在一起

c++ - 使用 SFINAE 的代码与 GCC 一起使用,但不与 Clang 一起使用