Skip to content

Exposing Eigen::Tensor To Python #2119

Closed
@afpgit

Description

@afpgit

I am trying to expose an Eigen tensor to python using pybind11. I can compile everything with no issue and can successfully import it to python. However, the data cannot be converted to a python type. I tried two methods. One is directly exposing the data and second using mapping. Both fail in python environment.

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
#include <pybind11/numpy.h>
#include <pybind11/eigen.h>
#include <unsupported/Eigen/CXX11/Tensor>

namespace py = pybind11;

class myclass{
    
    myclass(){
        m_data = new float[m_dim1*m_dim2*m_dim3]; // Contiguous data that represents a three dimensional array
        for(int i = 0; i<m_dim1*m_dim2*m_dim3; i++)
            m_data[i] = i;
        
        m_tensor = Eigen::TensorMap<Eigen::Tensor<float, 3>>(m_data, m_dim1, m_dim2, m_dim3);
    }
    
    Eigen::TensorMap<Eigen::Tensor<float, 3>>& getDataUsingMapping() { Eigen::TensorMap<Eigen::Tensor<float, 3>> temp(m_data, m_dim1, m_dim2, m_dim3);  return temp; }
    Eigen::Tensor<float, 3>& getDataWithoutUsingMapping() { return m_tensor};
    
    
private:
    Eigen::Tensor<float, 3> m_tensor;
    // In fact, m_data, m_dim1, m_dim2, m_dim3 all are
    // read from a data file but for this example let's 
    // assume some values.
    float* m_data; 
    int m_dim1 = 2, m_dim2 = 5, m_dim3 = 10;
}


PYBIND11_MODULE(example, m) {
    py::class_<myclass>(m, "myclass")
        .def(py::init<>())
        .def("getDataUsingMapping", &myClass::getDataUsingMapping, py::return_value_policy::reference)
        .def("getDataWithoutUsingMapping", &myClass::getDataWithoutUsingMapping, py::return_value_policy::reference);
}

I would like to be able to process this 3D array in python with its dimensional information (m_dim1, m_dim2, m_dim3).

Here are the error messages I get after trying to get the data in python.

>>> import example
>>> d = example()
>>>
>>> DataInPython = d.getDataUsingMapping()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Unable to convert function return value to a Python type! The signature was
		(self: example) -> Eigen::TensorMap<Eigen::Tensor<float,3,0,__int64>,0,Eigen::MakePointer>
>>>
>>>
>>> DataInPython = d.getDataWithoutUsingMapping()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Unable to convert function return value to a Python type! The signature was
		(self: example) -> Eigen::Tensor<std::complex<float>,3,0,__int64>

Did you forget to `#include <pybind11/stl.h>`? Or <pybind11/complex.h>,
<pybind11/functional.h>, <pybind11/chrono.h>, etc. Some automatic
conversions are optional and require extra headers to be included
when compiling your pybind11 module.

I tried including all pybdin11 include files but did not fix the problem. Could someone kindly help me?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions