pybind with array as class attribute

问题描述 投票:0回答:1

我想使用pybind将以下C ++代码包装到python中

class Galaxy {

public:
    double x[3];
    double v[3];

};

class GalaxyCatalogue {

public:
    long n_tracers;
    Galaxy *object;

    GalaxyCatalogue(long n_tracers);

    ~GalaxyCatalogue();

};

GalaxyCatalogue::GalaxyCatalogue(long n_tracers) : n_tracers(n_tracers) {

    std::cout << "from galaxies " << n_tracers << std::endl;
    object = new Galaxy[n_tracers];
    std::cout << "has been allocated " << std::endl;

}

GalaxyCatalogue::~GalaxyCatalogue() {

    delete[] object;

}

我遇到的第一个问题是Galaxy没有构造函数,所以我不知道该怎么做。即使我声明一个空构造函数,我也不知道如何处理数组,这样我在编译时就不会出错。这就是我尝试过的:

#include <pybind11/pybind11.h>
#include <iostream>
namespace py = pybind11;

class Galaxy {
   public:
  Galaxy();
 double x[3];
};

PYBIND11_MODULE(example, m){
  py::class_<Galaxy>(m, "Galaxy")
 .def(py::init<>())
 .def_readwrite("x", &Galaxy::x);
 }

这是我编译它的方式:

c++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` gal.cpp -o example`python3-config --extension-suffix`

这是我得到的错误:

In file included from gal.cpp:1:
/home/florpi/.conda/envs/virtualito/include/python3.5m/pybind11/pybind11.h: In instantiation of ‘pybind11::class_<type_, options>& pybind11::class_<type_, options>::def_readwrite(const char*, D C::*, const Extra& ...) [with C = Galaxy; D = double [3]; Extra = {}; type_ = Galaxy; options = {}]’:
gal.cpp:19:33:   required from here
/home/florpi/.conda/envs/virtualito/include/python3.5m/pybind11/pybind11.h:1163:65: error: invalid array assignment
                      fset([pm](type &c, const D &value) { c.*pm = value; }, is_method(*this));
                                                           ~~~~~~^~~~~~~
In file included from gal.cpp:1:

/home/florpi/.conda/envs/virtualito/include/python3.5m/pybind11/pybind11.h:64:5: error: ‘pybind11::cpp_function::cpp_function(Func&&, const Extra& ...) [with Func = pybind11::class_<type_, options>::def_readwrite(const char*, D C::*, const Extra& ...) [with C = Galaxy; D = double [3]; Extra = {}; type_ = Galaxy; options = {}]::<lambda(pybind11::class_<Galaxy>::type&, const double (&)[3])>; Extra = {pybind11::is_method}; <template-parameter-1-3> = void]’, declared using local type ‘pybind11::class_<type_, options>::def_readwrite(const char*, D C::*, const Extra& ...) [with C = Galaxy; D = double [3]; Extra = {}; type_ = Galaxy; options = {}]::<lambda(pybind11::class_<Galaxy>::type&, const double (&)[3])>’, is used but never defined [-fpermissive]
     cpp_function(Func &&f, const Extra&... extra) {
     ^~~~~~~~~~~~

先感谢您。

pybind11
1个回答
0
投票

在C ++中,你不能直接分配给一个数组,这就是pybind11在其包装魔法中试图做的事情。通常,C ++数组不是数值数组的很好的抽象。正如你所注意到的,你甚至不能说galaxy.x = other_galaxy.x

您最好的选择是使用更高级别的库来处理矩阵和向量,这将a)为您提供更好的编写C ++的经验b)执行更好的c)更清晰地映射到Python

Eigen是一个不错的选择。 pybind11自动知道如何将特征矩阵和向量映射到numpy数组。你的银河将成为:

class Galaxy {
  public:
    Eigen::Vector3d x;
    Eigen::Vector3d v;
};

如果你绝对不能这样做,你将不得不为属性提供手动getter / setter函数,你可以在其中进行python类型的转换:https://pybind11.readthedocs.io/en/master/classes.html?highlight=def_property#instance-and-static-fields

© www.soinside.com 2019 - 2024. All rights reserved.