Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PyBind11 Template Class of Many Types

I'd like to use PyBind11 to wrap a specialized array class. However, the array is available in many flavours (one per each plain-old-datatype). The code looks like this:

py::class_<Array2D<float>>(m, "Array2Dfloat", py::buffer_protocol(), py::dynamic_attr())
    .def(py::init<>())
    .def(py::init<Array2D<float>::xy_t,Array2D<float>::xy_t,float>())
    .def("size",      &Array2D<float>::size)
    .def("width",     &Array2D<float>::width)
    .def("height",    &Array2D<float>::height)
    //...
    //...

The only way I've thought of to tell PyBind11 about these classes is by duplicating the above for each POD through the use of a very large macro.

Is there a better way to do this?

like image 978
Richard Avatar asked Nov 25 '17 16:11

Richard


People also ask

What is template and types template?

A template is a C++ programming feature that permits function and class operations with generic types, which allows functionality with different data types without rewriting entire code blocks for each type.

What is the difference between class and template?

An individual class defines how a group of objects can be constructed, while a class template defines how a group of classes can be generated. Note the distinction between the terms class template and template class: Class template.

Can templates be used for classes?

A template is not a class or a function.

What is class template example?

Class Template: We can define a template for a class. For example, a class template can be created for the array class that can accept the array of various types such as int array, float array or double array.


1 Answers

You can avoid using macros and instead go with a templated declaration function:

template<typename T>
void declare_array(py::module &m, std::string &typestr) {
    using Class = Array2D<T>;
    std::string pyclass_name = std::string("Array2D") + typestr;
    py::class_<Class>(m, pyclass_name.c_str(), py::buffer_protocol(), py::dynamic_attr())
    .def(py::init<>())
    .def(py::init<Class::xy_t, Class::xy_t, T>())
    .def("size",      &Class::size)
    .def("width",     &Class::width)
    .def("height",    &Class::height);
}

And then call it multiple times:

declare_array<float>(m, "float");
declare_array<int>(m, "int");
...
like image 81
Hannes Ovrén Avatar answered Oct 08 '22 02:10

Hannes Ovrén