SWIG: передача двумерного массива в функцию C (двойное значение [])

Я использую SWIG с numpy.i для предоставления библиотеки C для Python. Функция, которую я пытаюсь обернуть, занимает серию double массивы в качестве аргументов:

int wcsp2s(struct wcsprm *wcs, int ncoord, int nelem, const double pixcrd[], double imgcrd[], double phi[], double theta[], double world[], int stat[]);

где некоторые массивы на самом деле двумерные, со степенью, определяемой ncoord а также nelem аргументы. У меня проблемы с этими двумерными массивами, так как numpy.i только кажется, что поддерживает вещи в форме int n1,int n2,double * arr или различные перестановки (и моя функция C не хочет эти дополнительные целые числа), или double arr[ANY][ANY], Последнее выглядело многообещающе, так как многомерный массив C является просто непрерывным блоком памяти и поэтому должен быть совместим с тем, что ожидает функция. Но когда я пытаюсь

%apply (double INPLACE_ARRAY2[ANY][ANY]) {(double imgcrd[]),(double world[])};

SWIG (точнее, gcc, работающий на выходе SWIG) жалуется:

wcs_wrap.c:3770:7: error: expected expression before ‘,’ token

Здесь SWIG сгенерировал недопустимый C-код для этих аргументов.

Возможно ли то, что я пытаюсь сделать здесь? Я думаю, я мог бы использовать% inplace и% rename, чтобы создать функцию-обертку, которая принимает (ненужные) измерения массивов, а затем вызывает реальную функцию. Даже лучше, чем описанный выше подход с массивами на месте, если бы я мог вернуть эти массивы в качестве выходных аргументов (их размеры легко вычислить на основе ncoord а также nelem,

Или, может быть, быстрый (т.е. не тот, что в astLib) интерфейс Python для libwcs уже существует, так что мне не нужно это делать?

Изменить: я только что обнаружил Pywcs (который имеет такое очевидное имя, что я должен был найти его во время моего первоначального поиска), который решает основную проблему.

Edit2: я полагаю, что обертка, которая принимает двумерные массивы и передает плоские изображения, обошла бы проблему, так как кажется, что одномерные массивы работают. Тем не менее, это приводит к необходимости большого количества файлов для простой оболочки (.i, _wrap.c, .py от swig и дополнительного.py для дальнейшей упаковки функций SWIG для решения проблемы размерности.

1 ответ

Решение

Мне также не хватает хорошей поваренной книги для использования numpy.i, Насколько я понимаю, вы можете либо:

  • передать массивы динамического размера, где вы также передаете размеры в качестве параметров функции. Если ваша функция ведет себя по-другому, напишите обертку (например, IN_ARRAY2 или же INPLACE_ARRAY2).
  • передать массивы фиксированного размера (например, IN_ARRAY2 или же INPLACE_ARRAY2).
  • При возврате массивов (например, ARGOUT_ARRAY1), вы должны передать размер при вызове из Python. В приведенном ниже примере вы должны написать oo = func3(20), Причина, по-видимому, в том, что python должен распределять память, он должен знать о размере,

Например, ваш .i-файл может выглядеть так:

...
%include "numpy.i"

%init %{
  import_array();
%}

// Pass  array of dynamic size:
%apply (double* INPLACE_ARRAY2, int DIM1, int DIM2) {(double *xx, int xx_n, int xx_m)};
void func1(double *xx,int xx_n, int xx_m);

// Pass array of fixed size:
%apply (int *INPLACE_ARRAY2[ANY][ANY]) { (double yy[4][4]) };
void func2(double yy[4][4]);

// Return a dynamic 1D array:
%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* out, int out_n)}
void func3(double* out, int out_n);

Конечно, вы можете объединить их - проверьте документы для получения дополнительной информации

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