I'm tying to wrap a C++ function (using Pybind11) that returns an STL container which is itself wrapped in a smart pointer. An example is shown below. The function is overloaded so I have to specify the signature.
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "my_class.h"
typedef std::array<std::complex<double>, 4> ArrayComplex4;
PYBIND11_MAKE_OPAQUE(ArrayComplex4);
namespace py = pybind11;
using namespace my_namespace;
PYBIND11_MODULE(my_module, m) {
py::class_<MyClass>(m, "MyClass", py::dynamic_attr())
.def("my_function", (std::unique_ptr<ArrayComplex4> (MyClass::*)(double)) &MyClass::my_function)
.def("my_function", (std::unique_ptr<ArrayComplex4> (MyClass::*)(double, double)) &MyClass::my_function);
}
The module will compile but it will give an error when I try to use the function in Python:
TypeError: Unable to convert function return value to a Python type!
I'm sure I'm just setting something up wrong for Pybind11. Thanks for any help!
EDIT
The problem was definitely in my attempt to bind the std::Array
data type. I ended up modifying the code to use std::Vector
and then Pybind11 had no issues. See AS Mackey's answer below for how one might bind the std::Array
containers.
The problem might be with the PYBIND11_MAKE_OPAQUE treatment of the ArrayComplex4 data structure, I couldn't get this to work, although I'll look at it some more when I get time.
The following code, which I did get to work, is my closest approximation so far to your design. I used an additional user-defined data structure to wrap the std:: elements:
NB I found that the additional pybind #includes were needed to make the python casting work.
The simple python code is:
This produces the following output, which looks correct:
I hope this gives you a starting point to work from. I'd be interested to know if you find a better alternative... Regards, AS