Как мне правильно предоставить пользовательский векторный класс, производный от Eigen::Matrix в pybind11?

#python #c #eigen #pybind11

#python #c #eigen #pybind11

Вопрос:

Я пытаюсь создать привязки к моему пользовательскому векторному классу, Vec3 который наследуется от класса matrix фиксированного размера Eigen::Vector3d , имеет конструктор копирования и реализует некоторые дополнительные методы. Все работает нормально, пока я не попытаюсь вызвать метод производного класса, где я получаю incompatible function arguments ошибку, хотя методы не принимают никаких аргументов.

Минимально воспроизводимый пример

bindings.cpp:

 #include <Eigen/Core>

#include "pybind11/pybind11.h"
#include "pybind11/eigen.h"

namespace py = pybind11;

class Vec3 : public Eigen::Vector3d {
 public:
  Vec3() : Eigen::Vector3d() {}
  Vec3(const Eigen::Vector3damp; v) : Eigen::Vector3d(v) {}
  Vec3(int rows, int cols) : Vec3() {}  // This constructor is needed for a problem-unrelated reason
  int f() { return 123; }  // I want to call this dummy method in python
};

PYBIND11_MODULE(Minimal, m) {
  py::class_<Vec3>(m, "Vec3")
    .def(py::init<>())
    .def(py::init<const Eigen::Vector3damp;>())
    .def("f", amp;Vec3::f);
}
  

Я использую pybind11 версии 2.4.3. CMakeLists.txt:

 cmake_minimum_required(VERSION 3.10)
project(Minimal)
find_package(Eigen3 REQUIRED NO_MODULE)

set(PYBIND11_CPP_STANDARD -std=c  17)
set(PYBIND11_PYTHON_VERSION 3.6)
add_subdirectory(pybind11)
pybind11_add_module(Minimal "${CMAKE_CURRENT_LIST_DIR}/bindings.cpp")
    
target_link_libraries(Minimal PRIVATE Eigen3::Eigen)
  

После компиляции это результат:

 $ python3 -c "from Minimal import Vec3; v = Vec3([0, 0, 0]); print(v.f());"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
TypeError: f(): incompatible function arguments. The following argument types are supported:
    1. (self: numpy.ndarray[float64[3, 1]]) -> int

Invoked with: <Minimal.Vec3 object at 0x7f4561fd35a8>
  

Что еще я пробовал

Я подозревал, что pybind11, возможно, не понял, что Vec3 наследуется от Eigen::Vector3d , поэтому я явно дал ему такое указание.

 PYBIND11_MODULE(Minimal, m) {
  py::class_<Eigen::Vector3d>(m, "Vector3d");
  py::class_<Vec3, Eigen::Vector3d>(m, "Vec3")
    .def(py::init<>())
    .def(py::init<const Eigen::Vector3damp;>())
    .def("f", amp;Vec3::f);

  // These two lines also didn't help
  // py::implicitly_convertible<Eigen::Vector3d, Vec3>();
  // py::implicitly_convertible<Vec3, Eigen::Vector3d>();
}
  

К сожалению, я столкнулся с той же ошибкой, что и выше. Кто-нибудь может мне помочь?

Комментарии:

1. если вы попытаетесь удалить базовый класс Eigen::Matrix из Vec3 и сделать Vec3 автономным, сработает ли это тогда?

2. Это работает, но я должен наследовать от Eigen::Matrix из-за ограничений компании.

Ответ №1:

Попробуйте удалить или закомментировать: #включить «pybind11/eigen.h»

Комментарии:

1. Это решило мой первоначальный вопрос, но мне пришлось его обновить. Класс по-прежнему должен тесно взаимодействовать с Eigen:: Matrix (я хочу иметь возможность инициализировать его путем передачи вектора, и есть пользовательские методы, которые должны возвращать собственные объекты), поэтому я думаю, что я не могу обойтись без python11/eigen.h . Без собственного заголовка конструктор копирования завершается ошибкой с: incompatible constructor arguments. The following argument types are supported: [...] Minimal.Vec3(arg0: Eigen::Matrix<double, 3, 1, 0, 3, 1>)