Я пытаюсь ускорить свой код Numpy и решил, что хочу реализовать одну конкретную функцию, где мой код большую часть времени проводил в C.
Я на самом деле новичок в C, но мне удалось написать функцию, которая нормализует каждую строку в матрице для суммирования до 1. Я могу скомпилировать ее и протестировать с некоторыми данными (в C), и она делает то, что Я хочу. В тот момент я очень гордился собой.
Теперь я пытаюсь вызвать мою славную функцию из Python, где она должна принимать массив 2d-Numpy.
Различные вещи, которые я пробовал:
SWIG
SWIG + numpy.i
ctypes
У моей функции есть прототип
void normalize_logspace_matrix(size_t nrow, size_t ncol, double mat[nrow][ncol]);
Таким образом, он берет указатель на массив переменной длины и изменяет его на месте.
Я попробовал следующий чистый интерфейсный файл SWIG:
%module c_utils
%{
extern void normalize_logspace_matrix(size_t, size_t, double mat[*][*]);
%}
extern void normalize_logspace_matrix(size_t, size_t, double** mat);
Тогда я бы сделал (в Mac OS X 64bit):
> swig -python c-utils.i
> gcc -fPIC c-utils_wrap.c -o c-utils_wrap.o \
-I/Library/Frameworks/Python.framework/Versions/6.2/include/python2.6/ \
-L/Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/ -c
c-utils_wrap.c: In function ‘_wrap_normalize_logspace_matrix’:
c-utils_wrap.c:2867: warning: passing argument 3 of ‘normalize_logspace_matrix’ from incompatible pointer type
> g++ -dynamiclib c-utils.o -o _c_utils.so
В Python я получаю следующую ошибку при импорте моего модуля:
>>> import c_utils
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define init function (initc_utils)
Далее я попробовал этот подход, используя SWIG + numpy.i
:
%module c_utils
%{
#define SWIG_FILE_WITH_INIT
#include "c-utils.h"
%}
%include "numpy.i"
%init %{
import_array();
%}
%apply ( int DIM1, int DIM2, DATA_TYPE* INPLACE_ARRAY2 )
{(size_t nrow, size_t ncol, double* mat)};
%include "c-utils.h"
Тем не менее, я не получаю дальше, чем это:
> swig -python c-utils.i
c-utils.i:13: Warning 453: Can't apply (int DIM1,int DIM2,DATA_TYPE *INPLACE_ARRAY2). No typemaps are defined.
SWIG, похоже, не находит таблицы типов, определенные в numpy.i
, но я не понимаю, почему, поскольку numpy.i
находится в том же каталоге, и SWIG не жалуется, что не может его найти.
С ctypes я не очень далеко продвинулся, но довольно быстро заблудился в документах, так как не мог понять, как передать ему 2d-массив, а затем получить результат обратно.
Так может кто-нибудь показать мне магический трюк, как сделать мою функцию доступной в Python / Numpy?