Как установить новый атрибут в Pybind11 для объекта Python в C ++? - PullRequest
0 голосов
/ 07 ноября 2019

Я пытаюсь создать новый класс Python в C ++ с pybind11, заполнить его данными, а затем вернуть его.

Например, возьмем простой класс в python, который затем используется в вызове функции c ++, скомпилированном с 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

Теперь используйте класс в c ++ с помощью 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);
  );

Идея заключается в том, чтобы иметь возможность использовать data_class_output в python и получать доступ, например, к значению data_class_output.new_data.

Обходной путь - определение класса data_class_output также в python, использование его в качестве дополнительного ввода и заполнение там значений.

Однако возможно ли работать описанным выше способом и определить «py :: object data_class_output» с нуля в c ++, а затем без проблем использовать его на python?

1 Ответ

0 голосов
/ 07 ноября 2019

Должен быть некоторый экземпляр объекта, к которому нужно присоединить новый атрибут. Этот объект, если вы хотите новый, должен быть создан из некоторого типа. Если на основании приведенного выше обсуждения вы хотите, чтобы тип вывода и тип ввода были одинаковыми, вы можете получить правильный тип из атрибута __class__ ввода. Затем, предполагая, что __init__ не принимает никаких дополнительных параметров, создайте экземпляр и прикрепите атрибут.

Рабочий пример, настроив ваш следующий параметр:

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

, после чего ваш фрагмент кода Python напечатает:

3.09999990463
...