Skip to content

[BUG]: How to create a class that has access to one or more Numpy arrays? #5036

@goofy2k

Description

@goofy2k

Required prerequisites

What version (or hash if on master) of pybind11 are you using?

2.11.1 (latest)

Problem description

I want to create a C++ class that can use a Numpy array. So I started to read the docs on using object-oriented code and Numpy arrays. I tested the examples in these sections and they behave well.

My own code for a class MC_box_1 is based on the struct Pet example (pybind11 documentation > Object-oriented code) and the modify_array example (pybind11 documentation > Python C++ interface >> Numpy). Both examples behave OK but when I combine them in a class MC_box_1 I get an error that is similar to the one described as in issue #2274 and have no clue how to solve this. I hope that someone can be of help on this.

My next step would be to insert the array already in the constructor.

My code:

Reproducible example code

// C++
// add a Numpy attribute (temp use setter)
class  MC_box_1 {
public:

    MC_box_1(const std::string& name) : name(name) { }
    void setName(const std::string& name_) { name = name_; }
    const std::string& getName() const { return name; }

    // preferably set input_array in constructor, first test with setArray
    void setArray(py::array_t<double> input_array_) {
        input_array = input_array_;
        py::buffer_info buf_info = input_array.request();
        double* ptr = static_cast<double*>(buf_info.ptr);
    }
    std::string name;
    py::array_t<double> input_array;
};
// binding code
    // add a Numpy array, later use it via the constructor
    py::class_<MC_box_1>(m, "MC_box_1")
        .def(py::init<const std::string&>())
        .def("setName", &MC_box_1::setName)
        .def("getName", &MC_box_1::getName)
        .def("setArray", &MC_box_1::setArray)
        //__repr__ method to print the object
        .def("__repr__",                           // Binding lambda functions
            [](const MC_box_1& a) {                // uses a "stateless" lambda closure [] (vs stateful)
                return "<MCrun_pybind_0.MC_box_1 named '" + a.name + " '>";
            });
//Python
    # Object oriented code
    p = MCrun_pybind_0.Pet("Molly")
    print(p)
    print(p.getName())
    p.setName("Charly")
    print(p.getName())                              # behaves OK
    
    mybox_0 = MCrun_pybind_0.MC_box_0("simple box") # based on pybind11 docs, struct Pet example
    print("print(mybox_0)",mybox_0)
    

    # first test Numpy array as such 
    arr = np.array([1.0, 2.0, 3.0, 4.0])
    print("type(arr) ",type(arr))          
    MCrun_pybind_0.modify_array(arr)                # taken from pybind11 docs
    print(arr)                                      # Expected output: [2.0, 4.0, 6.0, 8.0]   OK  
    
    arr_1 = np.array([1.0, 2.0, 3.0, 4.0])
    print("type(arr_1) ",type(arr_1))
    mybox_1 = MCrun_pybind_0.MC_box_1("box including Numpy array") # based on struct Pet (now class) and modify_array examples                    
    print("print(mybox_1)",mybox_1)                 # behaves OK
    
    MCrun_pybind_0.MC_box_1.setArray(arr_1)         # ERROR !

Although I use the same array and calling code as in the modify_array example I get an error on using the setArray method:

TypeError: setArray(): incompatible function arguments. The following argument types are supported:
1. (self: MCrun_pybind_0.MC_box1, arg0: numpy.ndarray[numpy.float64]) -> None

Invoked with: array([1., 2., 3., 4.])


### Is this a regression? Put the last known working version here if it is.

Not a regression

Metadata

Metadata

Assignees

No one assigned

    Labels

    triageNew bug, unverified

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions