Sam*_*TER 1 c++ python boost boost-python
我想将一个TestObj实例从C++代码传递给python.这里发布的代码在cout中产生错误:"为C++类型找不到to_python(by-value)转换器:class TestObj".如果我将对象创建移动main_module.attr("obj") = obj;到BOOST_PYTHON_MODULE宏中,代码运行正常.
当我尝试*TestObj使用或不使用boost :: ptr 时,会发生类似的事情.
testembed.py:
import sfgame
print("old x: " + str(obj.x))
obj.x = 10
print("new x: " + str(obj.x))
Run Code Online (Sandbox Code Playgroud)
testobj.h
class TestObj{
public:
TestObj();
int x;
int getX();
void setX(int xv);
};
Run Code Online (Sandbox Code Playgroud)
testobj.cpp
#include "TestObj.h"
TestObj::TestObj(){
}
int TestObj::getX(){
return x;
}
void TestObj::setX(int xv){
x = xv;
}
Run Code Online (Sandbox Code Playgroud)
main.cpp中
#include <boost/python.hpp>
#include "TestObj.h"
using namespace boost::python;
BOOST_PYTHON_MODULE(sfgame){
class_<TestObj>("TestObj")
.add_property("x", &TestObj::getX, &TestObj::setX)
;
}
int main(){
Py_Initialize();
object main_module = import("__main__");
object main_namespace = main_module.attr("__dict__");
TestObj obj;
try{
obj.setX(5);
main_module.attr("obj") = obj;
exec_file("testembed.py", main_namespace);
}
catch (const boost::python::error_already_set &){
PyObject *ptype, *pvalue, *ptraceback;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
std::string error;
error = boost::python::extract<std::string>(pvalue);
std::cout << error << std::endl;
}
system("PAUSE");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
通过Boost.Python将C++对象传递给Python具有相同的前提条件,无论调用它的上下文如何:必须为C++对象的类型注册to-Python转换器.
在创建实例时boost::python::class_<T>,to-Python和from-Python转换器会自动注册类型T.该BOOST_PYTHON_MODULE宏仅声明Python模块初始化函数,Python将在导入模块时调用该函数.在这种特殊情况下,可以通过在将TestObj实例传递给Python 之前执行以下任一操作来解决问题:
TestObj通过.class_main()sfgame模块.这需要通过Python初始化表明确添加模块初始化函数PyImport_AppendInittab().有关详情,请参阅此答案.不建议直接调用模块初始化函数.直接调用时,不会创建模块本身,但会使用Boost.Python注册类型.导入模块后,将创建并初始化模块,从而再次注册类型.在Boost.Python的调试版本中,这将使断言失败,并且在发布版本中它将打印警告.
这是一个完整的示例,演示了嵌入时将C++对象传递给Python.在示例中,spam如果在静态链接example模块egg中公开类型,则类型在__main__范围内公开.
#include <boost/python.hpp>
// Mockup models.
struct spam {};
struct egg {};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<spam>("Spam", python::init<>());
}
int main()
{
// Explicitly add initializers for staticly linked modules.
PyImport_AppendInittab("example", &initexample);
// Initialize Python.
Py_Initialize();
namespace python = boost::python;
try
{
// Create the __main__ module.
python::object main_module = python::import("__main__");
python::object main_namespace = main_module.attr("__dict__");
// Import the example module, this will cause the example module's
// initialization function to be invoked, registering the spam type.
// >>> import example
python::import("example");
// >>> spam = example.Spam()
spam spam;
main_namespace["spam"] = spam;
// Expose egg, defining it within the main module.
// >>> class Egg: pass
main_namespace["Egg"] = python::class_<egg>("Egg", python::init<>());
// >>> egg = Egg()
egg egg;
main_namespace["egg"] = egg;
// Verify variables and their types.
python::exec(
"import example\n"
"assert(isinstance(spam, example.Spam))\n"
"assert(isinstance(egg, Egg))\n",
main_namespace);
}
catch (const python::error_already_set&)
{
PyErr_Print();
return 1;
}
// Do not call Py_Finalize() with Boost.Python.
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1199 次 |
| 最近记录: |