boost::python:将 C++ class 公开给嵌入在 C++ 应用程序中的 python 脚本
boost::python: expose a C++ class to a python script embedded in a C++ app
我成功加载了 python 脚本文件并在 C++ 应用程序中使用 boost::python
调用函数。
在提升pythonEmbeddingPython 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
)
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
脚本工作正常:
test.py:
def run():
print "hello world"
输出:
hello world
将 C++ class 暴露给 python:
但是,我现在想向该脚本公开 C++ class。
struct Foo
{
void f() {}
};
根据 boost::python
文档,我将此 class 公开如下:
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
[=44= 不可见]
问题:
如何将我的 Foo
class 暴露给我正在加载的 test.py
python 脚本?
完整的工作示例:
test.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;
}
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++ 端将 FooModule
注入 Python 脚本,只需从 C++ 端向 PyImport_AppendInittab
注册模块,然后 import
它Python 方面:
import FooModule
def run():
foo = FooModule.Foo()
foo.f()
我成功加载了 python 脚本文件并在 C++ 应用程序中使用 boost::python
调用函数。
在提升pythonEmbeddingPython 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
)
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
脚本工作正常:
test.py:
def run():
print "hello world"
输出:
hello world
将 C++ class 暴露给 python:
但是,我现在想向该脚本公开 C++ class。
struct Foo
{
void f() {}
};
根据 boost::python
文档,我将此 class 公开如下:
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
[=44= 不可见]
问题:
如何将我的 Foo
class 暴露给我正在加载的 test.py
python 脚本?
完整的工作示例:
test.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;
}
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++ 端将 FooModule
注入 Python 脚本,只需从 C++ 端向 PyImport_AppendInittab
注册模块,然后 import
它Python 方面:
import FooModule
def run():
foo = FooModule.Foo()
foo.f()