我在C ++中有一个用pybind11包装到python中的类。该类具有std :: function,并且我想控制该函数的参数的处理方式(例如返回值策略)。我只是找不到执行此操作的语法或示例...
class N {
public:
using CallbackType = std::function<void(const OtherClass*)>;
N(CallbackType callback): callback(callback) { }
CallbackType callback;
void doit() {
OtherClass * o = new OtherClass();
callback(o);
}
}
用
包裹py::class_<OtherClass>(...standard stuff...);
py::class_<N>(m, "N")
.def(py::init<N::CallbackType>(),
py::arg("callback"));
我都工作:我可以在python中做到这一点:
def callback(o):
dosomethingwith(o)
k = N(callback)
,但是我希望能够控制调用callback(o);
时发生的情况-基本上,python然后是否将拥有包装的o
变量的所有权。
我将打印输出放在OtherClass的析构函数中,据我所知,它永远不会被调用。
答案 0 :(得分:1)
我在from keras.models import load_model
model = load_model('model.h5',custom_objects={'GroupNormalization' : GroupNormalization},compile=False)
中什么也没看到,因此您无法在调用时更改参数的所有权,因为所使用的pybind11/functional
是局部函数,因此不能专门化。您可以自己提供另一个包装器,但是在代码中您无法知道回调是Python函数还是绑定的C ++函数(嗯,从技术上讲,您可以确定该绑定的C ++函数是否由pybind11绑定,但是您不知道一般来说)。如果该函数是C ++,则更改包装器中的Python所有权将是错误的事情,因为即使该代理的有效载荷由C ++回调存储,该临时代理也可能会破坏该对象。
您可以控制struct func_wrapper
的实施吗?原因是通过使用class N
,所有您的所有权问题都会自动消失,而不管回调函数是C ++还是Python,以及是否存储参数。像这样工作,在上面的示例中进行扩展:
std::shared_ptr
答案 1 :(得分:1)
好的,我想我想通了:
使用pybind11 :: function代替std :: function
using CallbackType = pybind11::function
然后
void doit(const OtherClass &input) {
if (<I want to copy it>) {
callback(pybind11::cast(input, pybind11::return_value_policy::copy));
} else {
callback(pybind11::cast(input, pybind11::return_value_policy::reference));
}
}