返回SWIG中未指定大小的numpy数组

时间:2015-11-13 06:29:18

标签: python c numpy swig

我的目标是使用SW和C和Python来创建一个函数,该函数将NumPy数组作为输入并返回不同的NumPy数组。返回的数组具有一些取决于输入数组的未指定大小。不幸的是,当我尝试运行我的代码时,我得到了一个返回的空数组。这是一个显示问题的“最小”示例。我通过以下方式运行此代码:

python setup.py build_ext --inplace
python test.py

感兴趣的文件复制如下。如果您知道如何使此代码返回非空的NumPy数组,请告诉我。谢谢!

cancelterms.c:

#include "cancelterms.h"
void cancel(double complex* vec, int m, int n, double complex sum[])
{   

    // Some code that processes vec.

    // This is just an example. In practice the following lines will depend on vec.
    sum[0] = 1.0;
    sum[1] = 2.5;
    sum[2] = 3.6;
}

cancelterms.h:

#include <stdlib.h>
#include <stdio.h>
#include <complex.h>

void cancel(double complex* vec, int m, int n, double complex sum[]);

cancelterms.i:

%module cancelterms
%{
/* Put header files here or function declarations like below */
    #define SWIG_FILE_WITH_INIT
    #include "cancelterms.h"
%}

%include "numpy.i"
%include <complex.i>

%numpy_typemaps(double complex, NPY_CDOUBLE, int)

%init %{
    import_array();
%}

%apply (double complex* INPLACE_ARRAY2, int DIM1, int DIM2) {(double complex* vec, int m, int n)}
%apply (double complex ARGOUT_ARRAY1[ANY]) {(double complex sum[])}

%include "cancelterms.h"

setup.py:

# Import necessary modules.
from distutils.core import setup, Extension
import numpy as np

try:
    numpy_include = np.get_include()
except AttributeError:
    numpy_include = np.get_numpy_include()

example_module = Extension('_cancelterms', sources=['cancelterms.c', 'cancelterms.i'], include_dirs = [numpy_include])

setup(name='cancelterms', ext_modules=[example_module], py_modules=["cancelterms"])

test.py:

import cancelterms
import numpy as np

a=np.array([[1.0j,2.0j,3.0j,4.0j,5.0j,6.0j],[-1.0j,-2.0j,-3.0j,6.0j,7.0j,8.0j]])
print cancelterms.cancel(a)

不幸的是numpy.i太大了,无法在这里粘贴,但是我使用numpy github存储库中的标准numpy.i文件,其中包含一些小修改,我将双复合添加到类型列表中。

1 个答案:

答案 0 :(得分:0)

display:block类型地图适用于硬编码维度的数组。这在输出数组的numpy.i docs中清楚地说明,但也适用于其他数组。

例如,它们可以用作:

...[ANY]

如果你的函数采用了一个大小为5的数组(由调用者/在包装器代码中分配)。

关键是SWIG无法知道argout数组%apply (double complex ARGOUT_ARRAY1[ANY]) {(double complex sum[5])} 的大小。你的代码编译和运行完全是巧合。看看生成的包装器代码(搜索'wrap_cancel'),你会看到发生了什么。

还有以下类型图:

  • sum
    您可以在其中指定要预分配的数组的大小
  • ( DATA_TYPE* ARGOUT_ARRAY1, int DIM1 )
    数组由函数分配的位置,但另外返回分配的数组的大小。

在你的情况下,函数( DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1 )为数组cancel分配内存,假设调用者有某种方法来计算大小。这种情况没有预定义的类型图。

这类似于函数只返回sum的情况,并且如numpy.i文档中所述:

  

如果遇到函数或方法返回指向数组的指针的情况,最好的办法是编写自己要包装的函数版本,对于类方法的情况使用%extend或%对于函数的情况,忽略和%重命名。