Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exposing Eigen::Tensor To Python #2119

Closed
afpgit opened this issue Feb 24, 2020 · 4 comments · Fixed by #4201
Closed

Exposing Eigen::Tensor To Python #2119

afpgit opened this issue Feb 24, 2020 · 4 comments · Fixed by #4201

Comments

@afpgit
Copy link

afpgit commented Feb 24, 2020

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?

@ghost
Copy link

ghost commented May 21, 2020

@afalahat I have the same problem.
Did you fix your code?

@afpgit
Copy link
Author

afpgit commented Jun 15, 2020

I don't think exposing the tensor is doable as Eigen::Tensor is unsupported.

@bstaletic
Copy link
Collaborator

There's always an option of writing a custom caster. That said, a pull request would be welcome. We do need help maintaining the eigen.h header.

@sergiud
Copy link
Contributor

sergiud commented Nov 23, 2021

I wrote type casters for Eigen::Tensor of arbitrary rank (and OpenCV's cv::Mat), albeit using C++17 features. Maybe someone finds it useful and possibly can use the implementation as basis for a pybind11 submission.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants