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);
Конечно, вы можете объединить их - проверьте документы для получения дополнительной информации