使用SWIG操纵C内的Numpy数组

时间:2018-03-28 00:49:33

标签: python c numpy swig

尝试将Numpy数组传递给C方法并在那里修改其内容,它甚至可能吗?我们的想法是尽可能少地进行数据复制(速度和内存原因)。

目前尝试这样的事情:

test.c的

void testMethod(int** values) {
  // code
  *values = other_pointer;
}

test.i

/* File : test.i */
%module test
%{
  #define SWIG_FILE_WITH_INIT
%}
%include "numpy.i"

%init %{
    import_array();
%}

%{
extern void testMethod(int** values);
%}

%apply (int **ARGOUT_ARRAY1) {int **values};
extern void testMethod(int** values);

我修改了 numpy.i 文件,添加:

%typemap(in,
         fragment="NumPy_Fragments")
  (DATA_TYPE **ARGOUT_ARRAY1)
  (PyArrayObject* array=NULL, int is_new_object=0, DATA_TYPE* temp=NULL)
{
    array = obj_to_array_contiguous_allow_conversion($input,
                                                   DATA_TYPECODE,
                                                   &is_new_object);
    temp = (DATA_TYPE*) array_data(array);
    $1 = &temp;
}
%typemap(argout)
  (DATA_TYPE** ARGOUT_ARRAY1)
{
    $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum);
}

运行它:

input = numpy.array([1,2,3])
test.testMethod(input)

工作,即它编译,我可以用C打印数组的内容,但输入的内容保持不变。

1 个答案:

答案 0 :(得分:0)

要回答我自己的问题,一个有点hacky的方法是将类型映射更改为:

%typemap(in,
         fragment="NumPy_Fragments")
  (DATA_TYPE **ARGOUT_ARRAY1)
  (PyArrayObject* array=NULL, int is_new_object=0, PyArrayObject_fields* temp=NULL)
{
    array = obj_to_array_contiguous_allow_conversion($input,
                                                   DATA_TYPECODE,
                                                   &is_new_object);
    if (!array) SWIG_fail;
    temp = (PyArrayObject_fields*)array;
    $1 = (DATA_TYPE**) &temp->data;
}
%typemap(argout)
  (DATA_TYPE** ARGOUT_ARRAY1)
{
    $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum);
}

@Edit:经过一些测试后,如果我们重用Python input数组,上面的工作会有效,但会产生Segmentation Fault异常。解决方案是将映射类型从ARGOUT_ARRAY1更改为INPLACE_ARRAY1