Полностью прозрачная экспозиция типов Eigen :: Vector / Matrix с использованием pybind11 - PullRequest
0 голосов
/ 27 марта 2019

У меня есть простое определение класса:

class State {
  private:
      Eigen::Vector3f m_data;

  public:
      State(const Eigen::Vector3f& state) : m_data(state) { }
      Eigen::Vector3f get() const { return m_data; }
      void set(const Eigen::Vector3f& _state) { m_data = _state; }
      std::string repr() const {
          return "state data: [x=" + std::to_string(m_data[0]) + ", y=" + std::to_string(m_data[1]) + ", theta=" + std::to_string(m_data[2]) + "]";
      }
};

Затем я выставляю вышеизложенное в python с помощью pybind11:

namespace py = pybind11;

PYBIND11_MODULE(bound_state, m) {
    m.doc() = "python bindings for State";
    py::class_<State>(m, "State")
        .def(py::init<Eigen::Vector3f>())
        .def("get", &_State::get)
        .def("set", &_State::set)
        .def("__repr__", &_State::repr);
}

И все отлично работает; Я могу импортировать этот модуль в Python и создать экземпляр State с массивом numpy. Это не совсем то, что я хочу. Я хочу иметь возможность получить доступ к этому объекту, как если бы он был массивом; Я хочу иметь возможность сделать что-то вроде следующего в Python:

import bound_state as bs
arr = np.array([1, 2, 3])
a = bs.State(arr)
print(a[0])

(выше выдает TypeError: 'bound_state.State' object does not support indexing)

В прошлом я использовал boost :: python для предоставления списков с помощью add_property, и это позволяло индексировать базовые данные в C ++. у pybind11 есть что-то подобное, что может работать с Eigen? Может ли кто-нибудь предоставить пример, показывающий, как предоставить экземпляр State, который индексируется?

1 Ответ

0 голосов
/ 28 марта 2019

Согласно API Docs , это можно легко сделать с помощью метода def_property.

Превратить этот бит:

namespace py = pybind11;

PYBIND11_MODULE(bound_state, m) {
    m.doc() = "python bindings for State";
    py::class_<State>(m, "State")
        .def(py::init<Eigen::Vector3f>())
        .def("get", &State::get)
        .def("set", &State::set)
        .def("__repr__", &State::repr);
}

В это:

namespace py = pybind11;

PYBIND11_MODULE(bound_state, m) {
    m.doc() = "python bindings for State";
    py::class_<State>(m, "State")
        .def(py::init<Eigen::Vector3f>())
        .def_property("m_data", &State::get, &State::set)
        .def("__repr__", &State::repr);
}

Теперь со стороны Python я могу сделать:

import bound_state as bs
arr = np.array([1, 2, 3])
a = bs.State(arr)
print(a.m_data[0])

Это не точно , что я хочу, но шаг в правильном направлении.

...