Ste*_*mer 6 c++ python boost boost-python
我成功地能够加载python脚本文件并boost::python在C++应用程序中调用函数.
在boost python EmbeddingPython wiki中,有一个关于如何加载python模块的提示.
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"];
}
Run Code Online (Sandbox Code Playgroud)
我可以成功使用它来导入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;
}
Run Code Online (Sandbox Code Playgroud)
使用hello-world test.py脚本运行上面的代码可以正常工作:
test.py:
def run():
print "hello world"
Run Code Online (Sandbox Code Playgroud)
输出:
Run Code Online (Sandbox Code Playgroud)hello world
但是,我现在想要将C++类公开给该脚本.
struct Foo
{
void f() {}
};
Run Code Online (Sandbox Code Playgroud)
根据boost::python文档,我公开这个类如下:
BOOST_PYTHON_MODULE(FooModule)
{
bp::class_<Foo>("Foo")
.def("f", &Foo::f)
;
}
Run Code Online (Sandbox Code Playgroud)
根据上面链接的wiki中的说明,我可以导入我的FooModule,并将其存储在我的globals:
PyImport_AppendInittab("FooModule", &initFooModule);
...
bp::object Foo = bp::import("FooModule");
globals["Foo"] = Foo;
Run Code Online (Sandbox Code Playgroud)
这个导入是在导入我的test.py脚本之前完成的,这个globals对象是bp::exec导入我的脚本时传递给的对象(即:Foo 应该bp::exec在导入时暴露给我的脚本的全局字典中).
但是,出于某种原因,我的Foo模块不可见test.py
如何将我的Foo类暴露给test.py我正在加载的python脚本?
test.py:def run():
foo = Foo()
foo.f()
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
Output:Run Code Online (Sandbox Code Playgroud)>>> 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 脚本,只需从 C++ 端FooModule注册模块,然后从 Python 端注册模块:PyImport_AppendInittabimport
import FooModule
def run():
foo = FooModule.Foo()
foo.f()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
803 次 |
| 最近记录: |