python - 从 C 扩展返回 numpy 数组

标签 python c numpy python-c-api

为了学习新东西,我目前正在尝试在 C 中重新实现 numpy.mean() 函数。它应该采用 3D 数组并返回一个 2D 数组,其中元素沿轴 0 的平均值。我设法计算所有值的平均值,但真的不知道如何将新数组返回给 Python。

到目前为止我的代码:

#include <Python.h>
#include <numpy/arrayobject.h>

// Actual magic here:
static PyObject*
myexts_std(PyObject *self, PyObject *args)
{
    PyArrayObject *input=NULL;
    int i, j, k, x, y, z, dims[2];
    double out = 0.0; 

    if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &input))
        return NULL;

    x = input->dimensions[0];
    y = input->dimensions[1];
    z = input->dimensions[2];

    for(k=0;k<z;k++){
        for(j=0;j<y;j++){
            for(i=0;i < x; i++){
                out += *(double*)(input->data + i*input->strides[0] 
+j*input->strides[1] + k*input->strides[2]);
            }
        }
    }
    out /= x*y*z;
    return Py_BuildValue("f", out);
}

// Methods table - this defines the interface to python by mapping names to
// c-functions    
static PyMethodDef myextsMethods[] = {
    {"std", myexts_std, METH_VARARGS,
        "Calculate the standard deviation pixelwise."},
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC initmyexts(void)
{
    (void) Py_InitModule("myexts", myextsMethods);
    import_array();
}

到目前为止我的理解(如果我错了请纠正我)是我需要创建一个新的 PyArrayObject,这将是我的输出(可能与 PyArray_FromDims?)。然后我需要一个地址数组到这个数组的内存并用数据填充它。我该怎么做?

编辑:

在对指针做了更多阅读后(此处:http://pw1.netcom.com/~tjensen/ptr/pointers.htm),我实现了我的目标。现在出现另一个问题:我在哪里可以找到 numpy.mean() 的原始实现?我想看看它是怎么回事,python 操作比我的版本快得多。我假设它避免了丑陋的循环。

这是我的解决方案:

static PyObject*
myexts_std(PyObject *self, PyObject *args)
{
    PyArrayObject *input=NULL, *output=NULL; // will be pointer to actual numpy array ?
    int i, j, k, x, y, z, dims[2]; // array dimensions ?
    double *out = NULL;
    if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &input))
        return NULL;

    x = input->dimensions[0];
    y = dims[0] = input->dimensions[1];
    z = dims[1] = input->dimensions[2];
    output = PyArray_FromDims(2, dims, PyArray_DOUBLE);    
    for(k=0;k<z;k++){
        for(j=0;j<y;j++){
            out = output->data + j*output->strides[0] + k*output->strides[1];
            *out = 0;
            for(i=0;i < x; i++){
                *out += *(double*)(input->data + i*input->strides[0] +j*input->strides[1] + k*input->strides[2]);
            }
            *out /= x;
        }
    }
    return PyArray_Return(output);
}

最佳答案

Numpy API 有一个函数 PyArray_Mean,它可以在没有“丑陋的循环”的情况下完成您想要做的事情;)。

static PyObject *func1(PyObject *self, PyObject *args) {
    PyArrayObject *X, *meanX;
    int axis;

    PyArg_ParseTuple(args, "O!i", &PyArray_Type, &X, &axis);
    meanX = (PyArrayObject *) PyArray_Mean(X, axis, NPY_DOUBLE, NULL);

    return PyArray_Return(meanX);
}

关于python - 从 C 扩展返回 numpy 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16585083/

相关文章:

c - 是否可以将变量从一个进程传递到另一个进程?

c - 指针、结构和 malloc()

python - 在python中将数组写入h5

python - 如何将 numpy 数组保存到计算机中供以后在 python 中使用

python - 在调用堆栈中使用 Tornado 协程

python - 使用 Django 将 Assets 通过管道传输到 CDN 的最佳方式是什么?

python - 如何高效地执行循环语句进行数据分析?

python - 如何使用层次聚类将聚类分配给新的观察结果(测试数据)?

c - 信号量semget方法返回值确认

python - 将图像 opencv c++ 发送到 python