我用SWIG编写了一个用于C++ 14库的Python包装器。 在C++ API中,我可以登记STD::函数作为回调。在
我有一个std::function的SWIG类型映射来传递lambda表达式 调用Python回调:
%typemap(in) std::function {
auto callback = [$input](auto&&... params) {
PyGILState_STATE state = PyGILState_Ensure();
PyObject* result = PyObject_CallFunctionObjArgs($input,makePyObject(std::forward<decltype(params)>(params))..., NULL);
const int retVal = PyObject_IsTrue(result);
Py_DECREF(result);
PyGILState_Release(state);
return retVal == 1;
};
$1 = std::move(callback);
}
当我运行一个测试脚本时,下面的Python表达式可以工作 罚款:
^{pr2}$但是,此表达式不起作用:
self.cppInterface.registerFunc(lambda a,b: self.doStuff)
当我把lambda直接传递给寄存器函数时, 当从C++调用回调时,我得到以下错误:
TypeError: 'managedbuffer' object is not callable
为什么PyObject$input不可调用? 如何允许这两个Python表达式?在
示例代码:
看来你有参考计数问题。您需要保留对
$input
的引用,即使在std::function
类型映射完成之后也是如此。否则,一旦对registerFunc
的调用完成,它将丢失一个引用。最简单的方法是让您的类型映射捕获std::shared_ptr
,而不是原始的PyObject
,例如:理想情况下,我应该使用
std::unique_ptr
,但即使使用generalised lambda captures来阻止复制构造,并迫使SWIG不需要生成代码,也需要做更多的工作。在我可能会在类型映射中至少抛出一个
PyCallable_Check
,以便更好地度量。在相关问题 更多 >
编程相关推荐