如何在std :: function的pybind11包装中控制参数传递策略?

时间:2020-02-07 18:13:40

标签: pybind11

我在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的析构函数中,据我所知,它永远不会被调用。

2 个答案:

答案 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));     
        }
   }