pybind11 how to use custom type caster for simple example class

断了今生、忘了曾经 提交于 2020-02-06 04:18:41

问题


Motivation

I am currently trying to use a custom class both in python and in c++ with pybind11. The motivation behind this is to use a python-trained classifier within c++.

There are some working examples, e.g. in the official documentation https://pybind11.readthedocs.io/en/stable/advanced/cast/custom.html or by the nice examples from tdegeus https://github.com/tdegeus/pybind11_examples/blob/master/09_numpy_cpp-custom-matrix/pybind_matrix.h However, i still have problems to transfer this to a simple example with a custom class.

Below is a minimal working example with a wrapper function for pybind11 in c++ and the use of it in python.

#include <vector>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
namespace py = pybind11;

//A custom data class
class class_DATA{
    public: 
        std::vector<int> a;
};

//the actual function
class_DATA func_test(class_DATA data){
    std::vector<int> a = {1,2};
    data.a = a;
    return data; 
}

//the wrapper function that communicates with python
py::object wrapper(py::object data_py){
    class_DATA data_cpp = class_DATA();

    py::object a    = data_py.attr("a");
    data_cpp.a      = a.cast<std::vector<int>>();

    class_DATA data_result_cpp = func_test(data_cpp);

    py::object data_result_py   = data_py;
    data_result_py.attr("a")    = py::cast(data_result_cpp.a);

    return data_result_py;
}

//defining the modules
PYBIND11_MODULE(TEST,m){
  m.doc() = "pybind11 example plugin";
  //the test function
  m.def("func_test",  &wrapper);
 //the custom class
 py::class_<class_DATA>(m, "class_DATA", py::dynamic_attr())
  .def(py::init<>())    
  .def_readwrite("a", &class_DATA::a);
}

from build.Debug.TEST import func_test 

//the custom data class in python
class class_DATA_py:
    def __init__(self):
        self.a   = [0] 
test_py     = class_DATA_py()
data_return = func_test(test_py)

The output input is data.a = 0 and the output data_return.a = [1,2] as desired.

Question

How can I replace the wrapper function call with a custom caster? Most likely with the general shape outlined below (?)

namespace pybind11 { namespace detail {
    template <> struct type_caster<class_DATA> : public type_caster_base<class_DATA> {
        using base = type_caster_base<class_DATA>;
        public:
            PYBIND11_TYPE_CASTER(class_DATA, _("class_DATA"));
            // Conversion part 1 (Python->C++): 
            bool load(py::handle src, bool convert){
                PyObject *source = src.ptr();
                //what to do here?
                return true;
            }
            // Conversion part 2 (C++ -> Python): 
            static py::handle cast(class_DATA src, py::return_value_policy policy, py::handle parent){
                //what to do here?
                return base::cast(src, policy, parent);
            }
    };
}}

c++ is not my forte and python crashes repeatedly without any error messages when I meddle with this part, so any help would be really appreciated.

来源:https://stackoverflow.com/questions/57617361/pybind11-how-to-use-custom-type-caster-for-simple-example-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!