boost::python与swig集成
我有两个类,第一个叫“Radish”,第二个叫“RadishCont”。所有的代码都是用C++写的,需要在Python中使用。
Radish类已经通过SWIG暴露给Python;而RadishCont类则是通过boost::python暴露的。
我需要在RadishCont类中添加一个方法,语法如下:
Radish* get_radish()
{
return &radish;
}
这里的“radish”是一个包含在RadishCont中的Radish实例。
当我执行Python代码时,收到了这个异常:
TypeError: No Python class registered for C++ class Radish
所以,我的问题是:我该如何让这个方法在Python中工作,而不需要重新用SWIG编写RadishCont呢?
3 个回答
这个错误是来自Boost.Python的。Boost.Python的类型表里没有Radish的条目。没有这个条目,Boost.Python就不知道该怎么处理Radish。要想有这个条目,唯一的方法就是把Radish用Boost.Python包裹起来。
我担心Boost.Python和SWIG根本就不是为了能一起工作的,我非常怀疑你能在不进行大量修改的情况下让它们按照你想要的方式工作。
我建议你把整个系统迁移到其中一个库上,或者另一个库上。
我觉得你最好重新写一下你的SWIG接口,把新功能加进去。SWIG有一个内部的注册系统,用来处理类和函数,但这个系统和boost::python的系统不兼容(或者说,默认情况下是这样)。
最后,我成功了。
我在我的boost python模块中创建了一个类的实例,代码是这样的:
class_<Radish>("Radish");
我还创建了一个转换函数,代码如下:
static void* radishConvert(PyObject* obj)
{
char thisStr[] = "this";
//first we need to get the this attribute from the Python Object
if (!PyObject_HasAttrString(obj, thisStr))
return NULL;
PyObject* thisAttr = PyObject_GetAttrString(obj, thisStr);
if (thisAttr == NULL)
return NULL;
//This Python Object is a SWIG Wrapper and contains our pointer
void* pointer = ((PySwigObject*)thisAttr)->ptr;
Py_DECREF(thisAttr);
return pointer;
}
其中,PySwigObject是一个结构体,定义如下:
struct PySwigObject
{
PyObject_HEAD
void * ptr;
const char * desc;
};
最后,我注册了我的转换器,代码是:
boost::python::converter::registry::insert(&radishConvert, type_id<Radish>());
这一切都运行得很好,我可以从SWIG获取对象并将其传递给boost::python。虽然反向的过程还没有解决,但对我来说已经足够了。
这是我用来找到解决方案的指南: http://wiki.python.org/moin/boost.python/HowTo#SWIG_exposed_C.2B-.2B-_object_from_Python