- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我已经使用 SWIG 为 C++14 库编写了一个 Python 包装器。在 C++ API 中,我可以将 std::functions 注册为回调。
我有一个用于 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 表达式有效很好:
callback = lambda a,b: self.doStuff(a,b)
self.cppInterface.registerFunc(callback)
但是这个表达式不起作用:
self.cppInterface.registerFunc(lambda a,b: self.doStuff)
当我将 lambda 直接传递给 register 函数时,从 C++ 调用回调时出现以下错误:
TypeError: 'managedbuffer' object is not callable
为什么 PyObject $input 不是可调用的?如何允许两个 Python 表达式?
示例代码:
最佳答案
您似乎遇到了引用计数问题。您需要保留对 $input
的引用,即使在 std::function
类型映射完成之后。否则,一旦完成对 registerFunc
的调用,它就会丢失引用。最简单的方法是让你的类型映射捕获一个 std::shared_ptr
而不是原始的 PyObject
,例如:
%typemap(in) std::function {
Py_INCREF($input);
static const auto decref = [](PyObject *o) {
Py_DECREF(o); // This needs to be another lambda/function because Py_DECREF is really a macro
};
std::shared_ptr<PyObject> callable($input, decref);
auto callback = [callable](auto&&... params) {
PyGILState_STATE state = PyGILState_Ensure();
// Back to raw PyObject
PyObject* result = PyObject_CallFunctionObjArgs(callable.get(),makePyObject(std::forward<decltype(params)>(params))..., NULL);
int retVal = -1;
if (result)
{
retVal = PyObject_IsTrue(result);
Py_DECREF(result);
}
PyGILState_Release(state);
return retVal == 1;
};
$1 = std::move(callback);
}
理想情况下,我会使用 std::unique_ptr
,但即使使用 generalised lambda captures这会阻止复制构造成为可能,并迫使 SWIG 在不需要的情况下生成代码,这需要更多的工作。
不过,我可能会在类型映射中至少添加一个 PyCallable_Check
以作为良好的衡量标准。
关于python - 如何在 Python 中将 'managedbuffer' 转换为 Callable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50744038/
我已经使用 SWIG 为 C++14 库编写了一个 Python 包装器。在 C++ API 中,我可以将 std::functions 注册为回调。 我有一个用于 std::function 的 S
我是一名优秀的程序员,十分优秀!