pybind11 возвращает массив объектов numpy

Используя pybind11 C++ API и python3, как мы можем правильно создать пустой массив объектов (то есть строк Unicode) в реализации C++ и вернуть его обратно в python? Какова точная структура памяти базового массива данных, переданного в pybind11::array()? Как именно нам нужно управлять памятью, т.е. удалять/освобождать?

Обратите внимание, что это необходимо, потому что мы хотим использовать этот массив строк в сочетании с другими массивами POD при создании pandas DataFrame.


person joe-ts    schedule 16.07.2017    source источник
comment
Я не могу помочь с pybind11. Но массивы numpy можно создать с помощью функции numpy C API. Макеты массивов в основном одинаковы, атрибуты плюс буфер данных. Для типа объекта буфер данных содержит указатели на объекты в другом месте памяти. С типом unicode этот буфер фактически содержит строки (дополненные до указанной длины). Возможно, вам придется изучить numpy документы.   -  person hpaulj    schedule 16.07.2017
comment
спасибо - похоже, лучший способ - вручную создать буфер с объектами, а затем выяснить, как pybind11 может управлять памятью, связанной с базовым массивом, а также со всеми объектами...   -  person joe-ts    schedule 18.07.2017


Ответы (1)


Получается, что необходимо:

  1. создать массив указателей PyObject, заполнить массив, т.е.

    auto* pbuf = new PyObject*[arraySize]; // or create via pybind11 API...
    pbuf[0] = <new object...>
    pbuf[1] = <new object...>
    etc.
    
  2. создайте "объект" py::array() с капсулой:

    py::capsule freeWhenDone(pbuf, [](void* pp) {
            delete [] (PyObject*)pp; // or else properly free the pbuf memory
        });
    
    arr = py::array(py::dtype("object"),
        shape, strides, pbuf, freeWhenDone);
    
person joe-ts    schedule 20.07.2017
comment
Вы также знаете решение, которое не нуждается в freeWhenDone? Я предполагаю, что если память распределена pybind11, py::array может использовать обычное освобождение. - person olq_plo; 22.11.2019
comment
Я смог заставить его работать без утечек с помощью капсулы. Более того, когда внутренние объекты представляют собой строки Python, мне приходилось освобождать каждый отдельно выделенный объект. В более новой версии pybind11 могут быть другие решения. - person joe-ts; 24.11.2019