pythonc++c++11pybind11

Pybind11 can't figure out how to access tuple elements


I'm an experienced Python programmer trying to learn C++ to speed up some projects. Passing a py::tuple to a function, how do I access the elements?

Here's the constructor for a class I'm making to hold images from a video.

Buffer::Buffer(int size, py::tuple hw_args_) {

unsigned int frame_height = get<0>(hw_args_);
unsigned int frame_width = get<1>(hw_args_);

Buffer::time_codes = new int[size];
Buffer::time_stamps = new string[size];
Buffer::frames = new unsigned char[size][hw_args[0]][hw_args[1]];

if ((Buffer::time_codes && Buffer::time_stamps) == 0) {
    cout << "Error allocating memory\n";
    exit(1);
}

}

This gives me an error "No instance of the overloaded function 'get' matches the argument list, argument types are pybind11::tuple"

I've also tried setting the frame height and widths this way.

unsigned int frame_height = hw_args_[0];
unsigned int frame_width = hw_args_[1];

This gives an error "No suitable conversion function from 'pybind11::detail::tuple_accessor' to 'unsigned int' exists"

I'm at a loss, I can only seem to find info on making tuples in C++, not accessing them from Pybind11 / Python.


Solution

  • py::tuple has an operator[] that returns a detail::tuple_accessor which has a .cast as any py::object

    uint32_t frame_height = hw_args_[0].cast<uint32_t>();
    

    you could check its use from pybind11 tests

    [](const py::tuple &tup) {
      if (py::len(tup) != 4) {
        throw py::cast_error("Invalid size");
      }
      return SimpleStruct{tup[0].cast<bool>(),
                          tup[1].cast<uint32_t>(),
                          tup[2].cast<float>(),
                          tup[3].cast<long double>()};
            }