我正在尝试将python回调添加到C ++库中,如图所示:
template<typename T> void doCallback(shared_ptr<T> data) {
PyObject* pyfunc; //I have this already
PyObject* args = Py_BuildValue("(O)", data);
PyEval_CallObject(pyfunc,args);
}
这失败了,因为数据没有经过swig,而且不是PyObject。
我尝试使用:
swigData = SWIG_NewPointerObj((void*)data, NULL, 0);
但是因为它是一个模板,我真的不知道如何使用第二个参数。即使我对“正确的”SWIGTYPE进行硬编码,它通常也会在PyEval_CallObject上进行段错误。
所以我的问题是:
什么是调用swig的最好方法 打包?
我甚至走右边 方向在这?董事看了 有希望实施一个 回调,但我找不到 使用python的导演示例。
更新:正在生成正确的包装。我有其他函数返回shared_ptrs并可以正确调用它们。
答案 0 :(得分:0)
shared_ptr<T>
的 T
不是一种类型,因此SWIG无法包装它。您需要做的是为您打算使用的每个shared_ptr
实例提供SWIG包装。因此,如果您希望能够doCallback()
同时使用shared_ptr<Foo>
和shared_ptr<Bar>
,则需要:
Foo
Bar
shared_ptr<Foo>
和shared_ptr<Bar>
。你可以这样做:
namespace boost {
template<class T> class shared_ptr
{
public:
T * operator-> () const;
};
}
%template(FooSharedPtr) boost::shared_ptr<Foo>;
%template(BarSharedPtr) boost::shared_ptr<Bar>;
答案 1 :(得分:0)
我的第一个回答完全误解了这个问题,让我们再试一次。
您的核心问题是T
定义中的免费类型参数doCallback
。正如您在问题中指出的那样,shared_ptr<T>
没有具体值的T
中无法生成SWIG对象:shared_ptr<T>
实际上并不是一个类型。
因此,我认为您必须专门化:对于主机系统使用的doCallback
的每个具体实例化,为目标类型提供模板专门化。完成后,您可以生成一个Python友好的data
包装,并将其传递给您的python函数。最简单的技术可能是:
swigData = SWIG_NewPointerObj((void*)(data.get()), SWIGType_Whatever, 0);
...虽然这只有在你的Python函数没有在任何地方保存其参数时才有效,因为shared_ptr
本身不会被复制。
如果确实需要保留对data
的引用,则需要使用SWIG通常用于包装shared_ptr
的任何机制。如果没有特殊情况的智能指针魔术,它可能就像:
pythonData = new shared_ptr<Whatever>(data);
swigData = SWIG_NewPointerObj(pythonData, SWIGType_shared_ptr_to_Whatever, 1);
无论如何,你有一个易于使用Python的SWIG对象,可以使用Py_BuildValue()
。
希望这有帮助。