【问题标题】:Module level numpy array using SWIG使用 SWIG 的模块级 numpy 数组
【发布时间】:2013-01-03 09:17:29
【问题描述】:

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

【问题讨论】:

  • 不知道如何使用 swig 来实现(也许最简单的解决方案只是一个返回它的函数),但是更改数组 data 结构成员肯定是大错特错。有PyArray_SimpleFromData之类的……
  • 感谢您的提示!我已更正该示例以反映您的建议。如果我不得不求助于手动包装数组,我一定会使用这个函数。
  • 当您投反对票时,解释原因会很有帮助,以便 OP 可以改进问题。

标签: python numpy swig


【解决方案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 一起导入。

我现在得到了想要的结果:

>>> 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'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-06
    • 1970-01-01
    • 2014-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多