【问题标题】:C Function in Python: Return an Array and VariablesPython 中的 C 函数:返回数组和变量
【发布时间】:2015-05-04 05:17:45
【问题描述】:

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

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

所以我希望在 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();
}

【问题讨论】:

  • 这段代码给你什么行为?你希望它表现如何?
  • 如果您打算使用 Numpy 作为 matlab 替代品,请查看带有 numpy 的 swig。它使 python 与 C 函数(例如,甚至使用 openmp)的接口变得容易,以便快速计算。
  • 这个代码不起作用,因为你不能返回两个变量。

标签: python c arrays function return


【解决方案1】:

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

运行 Anaconda 2.7,64 位,win7x64

谢谢你,干杯,

【讨论】:

    【解决方案2】:

    可以使用 Cython 从 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
    

    可以用下面的setup.py编译,

    from distutils.core import setup, Extension
    import numpy as np
    from Cython.Distutils import build_ext
    
    setup(
        ext_modules=[Extension("myfunc", ["myfunc.pyx"])],
        cmdclass = {'build_ext': build_ext},
        include_dirs=[np.get_include()])
    

    使用

    $ python setup.py build_ext --inplace
    

    这会生成并编译myfunc.c。然后可以按如下方式使用生成的 Python 模块,

    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.]]
    

    请注意,在这种情况下,不必将数组维度 NxNy 传递给函数,因为它们可以通过 Cython 中的 inArray.shape 访问。

    请参考Cython documentation关于 Numpy 的更多优化细节。

    【讨论】:

    • 我尽量不使用 Cython。但我会检查你在这里做了什么 :-)
    • 好的,我在编译上面的代码时得到了一个错误列表。我正在使用 Python 2.7 - 64 位。
    • @user4627923 python 2.7,numpy 0.19,cython 0.22 我没有收到任何错误。您收到的错误信息是什么?顺便说一句,print(outArray) 之后的所有内容都是脚本的输出,不能使用。
    • @ user4627923 实际上,不,这些不是错误,只是警告(在名为 SomethingError 的函数中,这令人困惑),并且生成了编译模块。这些警告不会在 linux 上发生,我不确定为什么它们会在 Windows 上的 Anaconda 上发生(我确实得到了相同的警告)。仍然似乎主要是由于其他地方的字符串格式存在一些问题,因此与手头的问题无关。导入myfunc 并运行上面的示例应该可以工作)
    • @user4627923 这不是很关键,但是with nogil 释放了 Python 的全局解释锁 (GIL),它特别允许 parallel OpenMP calculations with Cython
    猜你喜欢
    • 2013-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-15
    • 2015-08-17
    • 1970-01-01
    • 2015-09-04
    • 1970-01-01
    相关资源
    最近更新 更多