使用SWIG的模块级numpy数组

时间:2013-01-03 09:17:29

标签: python numpy swig

我正在为我编写的科学C库创建一个python包装器。该库包含一个在编译时全局定义的常量双精度数组,即

const double arr[NARR] = { 200.0, 201.0, ... 899.0, 900.0 };

我想在我的python模块中使用SWIG使其成为模块级numpy数组,即

>>> import foo
>>> foo.arr
array([200.0, 201.0, ..., 889.9, 900.0])

我似乎无法通过常量数组在文档中找到任何内容。一切似乎都处理从函数返回numpy数组或定义非数组常量。

我知道如何通过手动包装数组来实现这一目的:

npy_intp dim[1] = { NARR };
PyObject *a = PyArray_SimpleNewFromData(1, dim, NPY_DOUBLE, arr);
PyObject_SetAttrString(module, "arr", a);

我无法让它与SWIG合作。当我尝试将上面的代码放在我的foo.i文件的init块中时,“arr”变量不会显示在foo模块中。

有谁能告诉我如何让它正常工作?

修改

根据seberg的建议更改了手动包装数组的代码示例。

1 个答案:

答案 0 :(得分:1)

我已经找到了解决这个问题的方法,但它非常讨厌。

我在foo.i文件中包含了两个代码扩展,一个在C中,另一个在python中。 C扩展创建一个返回C数组的函数,以及一个告诉SWIG创建一个包装器的语句,该包装器将这个C数组作为一个numpy数组返回:

/* Tell SWIG I want the function to output a numpy array */
%apply double ARGOUT_ARRAY1[ANY] { double a[NARR] };
/* Create a function that returns a copy of the array */
%inline %{
void _get_arr(double a[NARR]) {
    for (int i = 0; i < NARR; i++)
        a[i] = arr[i];
}
%}

python扩展调用此函数并将其放入模块级numpy数组变量arr(并且我将其设置为只读以获得良好的度量):

%pythoncode %{
# Make the arr array a read-only module-level numpy array
arr = _get_arr()
arr.flags.writeable = False
%}

因为我要将其作为分发,所以我可以控制__init__.py文件中导入的函数,因此_get_arr不会导入foo {1}}。

我现在得到了预期的结果:

>>> import foo
>>> foo.arr
array([200.0, 201.0, ..., 889.9, 900.0])
>>> foo.arr[0] = 10
RuntimeError: array is not writeable
>>> foo._get_arr()
AttributeError: 'module' object has no attribute '_get_arr'