boost :: python:将C ++类暴露给C ++应用程序中嵌入的python脚本 [英] boost::python: expose a C++ class to a python script embedded in a C++ app

查看:79
本文介绍了boost :: python:将C ++类暴露给C ++应用程序中嵌入的python脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我能够成功加载python脚本文件并在C ++应用程序中使用boost::python调用函数.

I am successfully able to load a python script file and call a function within using boost::python in a C++ app.

在增强型python EmbeddingPython Wiki中,有关如何加载python模块.

In the boost python EmbeddingPython wiki there is a tip on 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)

I can successfully use this to import a python module (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脚本运行上述代码可以正常工作:

Running the above code with a hello-world test.py script works fine:

test.py:

def run():
    print "hello world"

输出:

hello world

将C ++类暴露给python:

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

Exposing a C++ class to python:

However, I now want to expose a C++ class to that script.

struct Foo
{
    void f() {}
};

根据boost::python文档,我将此类公开如下:

As per the boost::python documentation, I expose this class as follows:

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

根据上面链接的Wiki中的说明,然后我可以导入我的FooModule,并将其存储在我的globals中:

As per the instructions in the above-linked wiki, I can then import my FooModule, and store it in my globals:

PyImport_AppendInittab("FooModule", &initFooModule); 

...

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

此导入是在导入我的test.py脚本之前 完成的,并且此globals对象是导入我的脚本时传递给bp::exec的对象(即:Foo 应该包含在导入时bp::exec暴露给我的脚本的全局指令中.

This import is done prior to importing my test.py script, and this globals object is the one passed to bp::exec when importing my script (ie: Foo should be in the globals dict which bp::exec exposes to my script when importing).

但是,由于某些原因,test.py

However, for some reason my Foo module is not visible to test.py

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

How can I expose my Foo class to the test.py python script I am loading?

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;
}

Output:

>>> 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 ++一侧向Python脚本中注入FooModule,不如从C ++一侧向PyImport_AppendInittab注册模块,然后向从Python端来看:

Instead of trying to inject FooModule into the Python script from the C++ side, just register the module with PyImport_AppendInittab from the C++ side and then import it from the Python side:

import FooModule

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

这篇关于boost :: python:将C ++类暴露给C ++应用程序中嵌入的python脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆