1

I want to wrap the following C++ code into python using pybind

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;

}

The first problem I have is that Galaxy doesn't have a constructor, so I'm not sure what to do with that. Even if I declare an empty constructor I don't know how to treat the array in a way that I don't get an error when compiling. This is what I've tried:

#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);
 }

This is how I compile it:

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

and this is the error I get:

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) {
     ^~~~~~~~~~~~

Thank you in advance.

1 Answer 1

2

In C++, you can't assign directly to an array, which is what pybind11 is trying to do inside its wrapping magic. In general, C++ arrays are not great abstractions for numerical arrays. As you've noticed, you can't even say galaxy.x = other_galaxy.x.

Your best bet is to use a higher-level library for matrices and vectors, which will a) give you a much better experience writing your C++ b) perform better c) map more cleanly to Python

Eigen is a good choice. pybind11 automatically knows how to map Eigen matrices and vectors to numpy arrays. Your Galaxy would become:

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

If you absolutely can't do this, you'll have to supply manual getter/setter functions to the property, where you do your own conversion to and from python types: https://pybind11.readthedocs.io/en/master/classes.html?highlight=def_property#instance-and-static-fields

Sign up to request clarification or add additional context in comments.

1 Comment

Should you use exclusively 'lists' and you don't want to use another third-partly library you can also use std::vector, which is also wrapped by pybind11.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.