PyArray_SIZE的正确用法是什么?

时间:2015-08-11 15:37:20

标签: python c numpy

我是在C中操作numpy数组的新手。下面是一段代码,它让我1)将一维,64位浮点数numpy数组列表传递给C和2)循环遍历每一个数组,打印其内容。

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include "Python.h"
#include "numpy/arrayobject.h"
#include "list_of_ndarrays_lib.h"

void print_all(PyObject *list) {

    int i, j;
    PyArrayObject *arrayObj;
    double *arrayData;

    for (i = 0; i < PyObject_Length(list); i++) {

        arrayObj = (PyArrayObject *) PyList_GET_ITEM(list, i);

        arrayData = PyArray_DATA(arrayObj);
        for (j = 0; j < PyArray_SHAPE(arrayObj)[0]; j++) {
            printf("%f ", arrayData[j]);
        }
        printf("\n");

    }

}

此代码有效,但PyArray_SHAPE(arrayObj)[0]并未对n维数组进行推广,如果我将其替换为PyArray_SIZE(arrayObj),则会出现分段错误。

PyArray_SIZE我做错了什么?

3 个答案:

答案 0 :(得分:2)

只需在print_all()开头添加$(document).ready(function() { initMap(); }); 调用即可。它将初始化数组函数C-API。

答案 1 :(得分:0)

我已完成一些cython编码,但不是更基本的c工作。但是,由于没有其他人回答,我会抛出一些想法。

可能相关的doc部分是http://docs.scipy.org/doc/numpy/user/c-info.how-to-extend.html#getting-at-ndarray-memory-and-accessing-elements-of-the-ndarray

迭代数组的另一个工具是nditer。我熟悉它在pythoncython中的用法。有一个很好的介绍页面。

http://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#arrays-nditer http://docs.scipy.org/doc/numpy/reference/c-api.iterator.html

另一件事是查看numpy源代码。我将转到github存储库,并对此变量进行搜索。

使用SHAPE进行的迭代等同于:

for i in range(arr.shape[0]):
    print arr[i]

您的arrayData[j]使用与Python版本相同的数组索引代码。

2d等价物(在Python中)是:

for i in range(arr.shape[0]):
    for j in range(arr.shape[1]):
        print arr[i,j]

我怀疑c等价物有类似的结构。

for i in range (arr.size):
     print arr[i]

获得IndexError: index 3 is out of bounds for axis 0 with size 3。我认为没有边界检查你会得到一个分段错误。

我怀疑SIZE您需要直接通过DATA缓存,而不是使用某种形式的arrayData[j]。换句话说,获取缓冲区指针,并按itemsize SIZE次数执行。

nditer将为您节省大量详细工作。

numpy / core calculation.c中的几个地方。我看到一个像:

这样的块
n = PyArray_SIZE(ap)/m;
rptr = (npy_intp *)PyArray_DATA(rp);
for (ip = PyArray_DATA(ap), i = 0; i < n; i++, ip += elsize*m) {
    arg_func(ip, m, rptr, ap);
    rptr += 1;
}

如果m=1,这应该逐个ip指针遍历数据缓冲区,逐个元素(每个elsize个字节长),并将其传递给arg_func以进行操作。更常见的是PyArray_SIZE用于检查数组是否为空(== 0)。

另一个选择是使用PyArray_Flatten(或更好PyArray_Ravel)来展平数组,然后使用SHAPE次迭代。

答案 2 :(得分:0)

我认为这里的问题可能是所有Py *功能,包括PyArray *功能,都是风险,除非你正确地修改你的代码成为C扩展模块。

关于这个主题的明确说明是here。有一些样板,但除此之外,这种方法非常好。没有外部依赖(如Boost.Python),它使您的Python代码非常干净,无需通过ctypes指定函数签名。