我正在为我编写的科学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的建议更改了手动包装数组的代码示例。
答案 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'