Python中的C函数:返回数组和变量

Python中的C函数:返回数组和变量,python,c,arrays,function,return,Python,C,Arrays,Function,Return,我刚从Matlab转换成Python,我知道调用C函数与MatlabMex不同。由于缺乏适当的文档,我已经在网络上肆虐了好几天,找不到解决我这个简单问题的方法 基本上,我想在Python中调用一个C函数,输入2个整数和一个2D数组,进行一些计算,然后返回一个2D数组。我还想输出一些其他变量(这可能需要使用结构)。我知道这是非常基本的东西,但如果有人能帮助我,我将不胜感激 因此,我希望在matlab中得到与此等效的结果!谢谢 [Nxy,outArray]=函数(Nx,Ny,inArray) set

我刚从Matlab转换成Python,我知道调用C函数与MatlabMex不同。由于缺乏适当的文档,我已经在网络上肆虐了好几天,找不到解决我这个简单问题的方法

基本上,我想在Python中调用一个C函数,输入2个整数和一个2D数组,进行一些计算,然后返回一个2D数组。我还想输出一些其他变量(这可能需要使用结构)。我知道这是非常基本的东西,但如果有人能帮助我,我将不胜感激

因此,我希望在matlab中得到与此等效的结果!谢谢

[Nxy,outArray]=函数(Nx,Ny,inArray)

setup.py的代码

from distutils.core import setup, Extension
import numpy.distutils.misc_util

setup(
    ext_modules=[Extension("myfunc", ["myfunc.c"])],
    include_dirs=numpy.distutils.misc_util.get_numpy_include_dirs(),
)
myfunc.c的代码

static char module_docstring[] =
    "This function does some calculations...";
static char Run_docstring[] =
    "Run what ever algorithm there is!";

static PyObject *Run(PyObject *self, PyObject *args)
{
    int i, j, Nx, Ny;
    PyObject *Data;

    /* Parse the input tuple */
    if (!PyArg_ParseTuple(args, "iiO", &Nx, &Ny, &Data))   // Data is a 2D array  
        return NULL;

    PyObject *array = PyArray_FROM_OTF(Data, NPY_DOUBLE, NPY_IN_ARRAY); // Interpret as numpy array
    double *newData = (double*)PyArray_DATA(array); // Pointers to the data as C-types

    double outData[Ny][Nx]; // Creating output 2D Array
    int outCount;

    // Calculations
    outCount = Nx*Ny;

    for (i=0; i<Nx; i++){
        for (j=0; i<Ny; j++){
           outData[j][i] = sqrt(Data[j][i]) + sqrt(outCount);
        }
    }

    // Free memory used in PyObject
    Py_DECREF(array);

    // Return output Data
    PyObject *ret = Py_BuildValue("i", outCount);
    return ret, PyArray_Return(outData);   

}

static PyMethodDef module_methods[] = {
    {"Run", Run, METH_VARARGS, Run_docstring},
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC initmyfunc(void)
{
    PyObject *m = Py_InitModule3("myfunc", module_methods, module_docstring);
    if (m == NULL)
        return;
    import_array();
}
静态字符模块\u docstring[]=
“此函数进行一些计算…”;
静态字符Run_docstring[]=
“运行任何算法!”;
静态PyObject*运行(PyObject*自身,PyObject*参数)
{
int i,j,Nx,Ny;
PyObject*数据;
/*解析输入元组*/
如果(!PyArg_ParseTuple(args,“iiO”,&Nx,&Ny,&Data))//数据是一个二维数组
返回NULL;
PyObject*array=PyArray_FROM_OTF(Data,NPY_DOUBLE,NPY_IN_array);//解释为numpy数组
double*newData=(double*)PyArray_DATA(array);//作为C类型指向数据的指针
双输出数据[Ny][Nx];//创建输出2D数组
智力过剩;
//计算
超出数量=Nx*Ny;

对于(i=0;i,可以使用从Python调用优化的C函数

在这种特殊情况下,我们可以创建一个
myfunc.pyx
文件

import numpy as np
cimport numpy as np
from libc.math cimport sqrt

cpdef tuple myfunc(int Nx, int Ny, double[:,::1] inArray):

        cdef double [:,::1] outData = np.zeros((Nx, Ny))
        cdef int i,j, res

        with nogil:
            for i in range(Nx):
                for j in range(Ny):
                    outData[i, j] = sqrt(inArray[i,j]) + sqrt(<double> Nx*Ny)
        res = 0 # not sure how res is computed

        return res, outData.base
使用

这将生成并编译
myfunc.c

from myfunc import myfunc
import numpy as np
Nx, Ny = 2, 2
inArray =  np.ones((Nx,Ny))
res, outArray = myfunc(Ny,Ny, inArray)
print(outArray)
# which would return
[[ 3.  3.]
[ 3.  3.]]
请注意,在这种情况下,无需将数组尺寸
Nx
Ny
传递给函数,因为它们可以通过Cython中的
inaray.shape
访问


有关进一步优化的详细信息,请参阅关于Numpy的说明。

我遵循了rth的建议,在编译过程中收到了此错误消息

运行Anaconda 2.7,64位,win7x64

谢谢大家,干杯


这段代码给了您什么行为?您希望它表现如何?如果您打算使用Numpy作为matlab的替代品,请查看swig。它使python与C函数接口(例如,即使使用openmp)这段代码不起作用,因为你不能返回两个变量。我尽量不使用Cython。但我会检查你在这里做了什么thx:-)好的,在编译上述代码时,我得到了一个错误列表。我使用的是Python 2.7-64位。@user4627923 Python 2.7,numpy 0.19,cython 0.22我没有收到任何错误。您收到了什么错误消息?顺便说一句,
print(outArray)之后的所有内容
是脚本的输出,不可使用。@user4627923实际上,不,这些不是错误,只是警告(在名为SomethingerError的函数中,这很容易混淆),并且生成了编译的模块。这些警告在linux上不会发生,我不确定为什么在Windows上的Anaconda上会发生(我确实得到了相同的答案)。但这似乎主要是由于其他地方的字符串格式存在一些问题,因此与手头的问题无关。导入
myfunc
并运行上面的示例应该可以)@user4627923这在这里并不是很关键,但是nogil的
释放了Python的全局解释锁(GIL),它特别允许
$ python setup.py build_ext --inplace
from myfunc import myfunc
import numpy as np
Nx, Ny = 2, 2
inArray =  np.ones((Nx,Ny))
res, outArray = myfunc(Ny,Ny, inArray)
print(outArray)
# which would return
[[ 3.  3.]
[ 3.  3.]]