Лучший способ обернуть программу C для интерфейса Python с преобразованием между буфером данных в C и массив NumPy?

У нас есть заранее существующая большая библиотека изображений, написанная на C/C++, с уже существующим типом изображений. Мы хотели бы связать его с Python. Мы знаем, как сделать большинство вещей, например, используя SWIG, но мы бы хотели, чтобы наш интерфейс использовал NumPy вместо собственного типа структуры для хранения наших изображений.

У кого-нибудь есть пример как это сделать? В Интернете есть примеры, которые связывают NumPy с голыми указателями. Как мы можем связать NumPy с существующей структурой типа C, подобной этой:

typedef struct xvimage {

    int nx, ny, nz, nt ; // dimensions

    enum {PIX_UINT8, PIX_INT16, PIX_UINT16, PIX_INT32, PIX_FLOAT, PIX_DOUBLE} ; // type

    void *data;

} xvimage;

1 ответ

Похоже, у вас уже есть хороший ответ, но в случае, если это поможет другим, использующим C++, обернуть вектор, например, вот подпись C++: int sum_byte (const std:: vector& buf);

/* File : example.i */
%module example

%{
#include "../src/example.h"
%}

%include <std_string.i>
%include <stl.i>
%include <std_vector.i>
%include <stdint.i>
%include <cpointer.i>
%include <carrays.i>

namespace std {
  %template(IntVector)    vector<int>;
  %template(ByteVector)   vector<uint8_t>;
}

%include "../src/example.h"

Полный пример, с работающими скриптами python и ruby, показывающими, что он работает swig_examples_cpp

Есть в основном три способа:

  1. Скопируйте из буфера изображения в массив NumPy и наоборот. Если дано изображение C/C++, создайте массив NumPy и скопируйте данные, а когда получите массив NumPy, создайте изображение C/C++ и скопируйте данные.

  2. Массив NumPy в качестве обертки вокруг указателя данных C. Создайте массив NumPy, но с указанным указателем данных. Убедитесь, что ваше изображение C/C++, содержащее указатель данных, живет дольше, чем массив NumPy. Массив NumPy может жить короче, потому что в этом случае он не будет пытаться удалить данные.

  3. Буфер изображений C/C++ в качестве оболочки вокруг указателя массива NumPy. Создайте массив NumPy и извлеките указатель данных, а затем используйте его для манипулирования массивом NumPy на месте. Убедитесь, что массив NumPy живет достаточно долго, удерживая ссылку на Python.

Каждый из них может быть реализован в карте типов SWIG.

В любом случае вам нужно преобразование типов ваших типов в типы NumPy (NPY_UINT8, ..) и сохранение размеров изображения в npy_intp *,

Для создания массива NumPy используйте PyArray_New или же PyArray_SimpleNew или же PyArray_SimpleNewFromData ( Array API) и укажите желаемые флаги, такие как непрерывный стиль Фортрана или что угодно удобное для вас. Вы можете предоставить свой собственный указатель данных с PyArray_New а также PyArray_SimpleNewFromData,

Возвращаемое значение PyObject* которые можно смело приводить к PyArrayObject* (или выполнить PyArray_Check до) и указатель данных извлекается PyArray_DATA ( Array API), который возвращает void * который вы можете затем привести к желаемому типу. Затем вы можете выполнить копирование или выполнить модификацию на месте по желанию.

Чтобы добавить ссылку на объект Python, используйте Py_INCREF а также Py_DECREF ( doc) на случай, если вы хотите избежать преждевременного удаления массива NumPy.

Если вы хотите получать уведомления, когда объект Python собирается собирать мусор, используйте слабую ссылку через PyWeakref_NewRef ( док).

Другие вопросы по тегам