Reputation: 51
I am trying to create a new python class in c++ with pybind11, fill it with data and then return it.
For example, take a simple class in python, which is then used in a c++ function call compiled with pybind11.
from TEST import func_wrapper
class class_DATA_py:
def __init__(self):
self.a = 1
data_class_input = class_DATA_py()
data_return = func_wrapper(data_class_input) #is not compiling
print(data_return.new_data) #is what I wish to see
Now use the class in c++ with the help of pybind 11.
#include <pybind11/pybind11.h>
namespace py = pybind11;
py::object func_wrapper(py::object data_class_input){
//1) read in the data of some python class
int a = data_class_input.attr("a").cast<int>();
//2) do something
float new_data = 3.1; //just an example value
//3) make the results accessible from python:
py::object data_class_output;
//This is where things go wrong and crashes during compilation
//Is there a way to set an attribute so that I can write something like below?
data_class_output.attr("new_data") = py::cast(new_data);
return data_class_output;
}
//pybind11-related:
PYBIND11_MODULE(TEST,m){
m.doc() = "pybind11 example plugin";
m.def("func_wrapper", &func_wrapper);
);
The idea is then to be able to use the data_class_output in python and access for example the data_class_output.new_data value.
A workaround is defining the data_class_output class also in python, use it as an additional input and fill the values there then.
However, is it possible to work in the way outlined above and define the "py::object data_class_output" from scratch in c++ and then use it in python without problems?
Upvotes: 0
Views: 4902
Reputation: 3788
There needs to be some object instance to attach the new attribute to. This object, if you want a new one, will need to be created from some type. If based on the discussion above you want the output type and input type to be the same, you can get the proper type from the __class__
attribute of the input. Then, assuming __init__
takes no additional parameters, create an instance and attach the attribute.
Working example by adjusting yours follows:
#include <pybind11/pybind11.h>
namespace py = pybind11;
py::object func_wrapper(py::object data_class_input){
//1) read in the data of some python class
int a = data_class_input.attr("a").cast<int>();
//2) do something
float new_data = 3.1; //just an example value
//3) make the results accessible from python:
py::object data_class_input_type = data_class_input.attr("__class__");
py::object data_class_output = data_class_input_type();
data_class_output.attr("new_data") = py::cast(new_data);
return data_class_output;
}
//pybind11-related:
PYBIND11_MODULE(TEST,m){
m.doc() = "pybind11 example plugin";
m.def("func_wrapper", &func_wrapper);
}
after which your python snippet will print:
3.09999990463
Upvotes: 3