我正在尝试使用嵌入在C ++中的Python和Boost :: python。
我的嵌入式脚本应该使用装饰器来注册他们的方法如下:
class Test:
def __init__(self, object_id):
self.object_id = object_id
@decorator('my_id_1')
def func1(self):
print("{}.func1".format(self.object_id))
在C ++端声明了 decorator
,定义了__init__
和__call__
的方法。一切正常,直到调用方法,导致SIGSEGV或SIGARBT。
以下是我想用Python做的一个例子:
#CPP side
item = {}
class decorator:
def __init__(self, _id):
self._id = _id
def __call__(self, func):
item[self._id] = func #saved as PyObject* in CPP
print func
return func
#Script side
class Test(CppBase):
def __init__(self, object_id):
CppBase.__init__(self)
self.object_id = object_id
@decorator('my_id_1')
def func1(self):
print("{}.func1".format(self.object_id))
@decorator('my_id_2')
def func2(self):
print("{}.func2".format(self.object_id))
#CPP side
obj1 = Test("obj1")
item['my_id_1'](obj1) #The crash append here
要进行通话,我使用以下功能:boost::python::call<void>(my_PyObject_func, boost::ref(my_obj_instance))
我不会把我所有的C ++代码都放在一起,因为我实际上正在更新一个由旧的Python C API构建的工作项目,整个API非常庞大。但是,如果您认为我忘了它的一些重要部分,请告诉我,我会发布这些部分。此外,我删除了很多简单的检查,例如确保全局Python var包含我的对象,没有发生python错误或者哈希包含请求的id,以使代码更轻。
这是我的C ++对象定义
class CppBase: public boost::python::object {
public:
CppBase();
void open(std::string, boost::python::tuple arg);
void setRoutes(const std::hash<std::string, const Route*>&);
inline std::hash<std::string, const Route*>*const routes() const { return route; }
private:
std::string name;
QHash<std::string, const Decorator*> *route;
};
class Decorator {
public:
Decorator(std::string identifier);
PyObject* call(PyObject* func);
void invoke(boost::python::object&, boost::python::tuple) const;
static void commit(CppBase&);
private:
PyObject* method;
std::string identifier;
static std::hash<std::string, const Decorator*> routes;
};
以下是我注册Python模块的方法
BOOST_PYTHON_MODULE(app)
{
boost::python::class_<CppBase, boost::noncopyable>("CppApp") //I tried to remove 'noncopyable', nothing change
;
boost::python::class_<Decorator, boost::noncopyable>("decorator", boost::python::init<std::string>())
.def("__repr__", &Decorator::repr)
.def("__call__", &Decorator::call)
;
}
以下是CppBase::open
的实现,我认为这是我班级定义中唯一重要的实现。
...
void CppBase::open(std::string id, boost::python::tuple arg /* unused so far */){
boost::python::call<void>(route->value(id), boost::ref(*this))
}
...
以下是使用此示例运行的Python脚本示例:
class MyScriptSubClass(CppApp):
def __init__(self, object_id):
CppBase.__init__(self)
self.object_id = object_id
@decorator('my_id_1')
def func1(self):
print("{}.func1".format(self.object_id))
以下是我尝试使一切正常的方法
//... Creating Python context, Executing the Script file...
boost::python::object cls(main_module.attr("MyScriptSubClass")); //Getting the classDefinition
CppBase core = boost::python::extract<CppBase>(cls()); //Instanciating the object with the previous catched definition
Decorator::commit(core); //Save all the decorator intercepted until now into the object
core.open('my_id_1'); //Calling the function matching with this id
我希望我把事情弄清楚。
事先,谢谢。