xtensor-stack / xtensor-python

Python bindings for xtensor
BSD 3-Clause "New" or "Revised" License
345 stars 58 forks source link

Support for custom types? #285

Open lamyj opened 1 year ago

lamyj commented 1 year ago

I'm trying to wrap a custom type using pybind11 and xtensor-python. Although I can create a numpy array of my wrapped type from Python, I cannot pass this numpy array to C++ functions or pass xt::xarray to Python.

The C++ part is

#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>

#include <xtensor/xarray.hpp>
#define FORCE_IMPORT_ARRAY
#include <xtensor-python/pyarray.hpp>

struct Quantity
{
    double q;

    Quantity(double q=0)
    : q(q)
    {
    }
};

PYBIND11_MODULE(test_array, test_array)
{
    xt::import_numpy();

    pybind11::class_<Quantity>(test_array, "Quantity")
        .def(pybind11::init<double>())
        .def_readwrite("q", &Quantity::q);

    test_array.def("create", []() { return xt::xarray<Quantity>{1.1, 2.2}; });
    test_array.def(
        "consume", [](xt::xarray<Quantity> const & array) {
            for(auto && item: array)
            {
                std::cout << item.q << "\n";
            }
        });
}

And the Python code

import numpy
import test_array

q1 = test_array.Quantity(42)
q2 = test_array.Quantity(3.14)
a = numpy.array([q1, q2])

print([x.q for x in a])

try:
    test_array.create()
except Exception as e:
    print(e)

try:
    test_array.consume(a)
except Exception as e:
    print(e)

Both try/except blocks in Python yield a RuntimeError saying "NumPy type info missing for 8Quantity"

Is this use case supported by xtensor-python? If so, what am I missing? If not, what alternative would you suggest?

tdegeus commented 1 year ago

I don't think that this is supported. You are welcome to figure out if this could be done ;) I have no use case for this, so I won't be able to push this