从 C 代码调用 numpy 函数

Posted

技术标签:

【中文标题】从 C 代码调用 numpy 函数【英文标题】:Calling numpy function from C-code 【发布时间】:2013-04-18 03:30:34 【问题描述】:

我正在尝试将一些带有 Mex 扩展的 MatLab 代码移动到带有 numpy 和 scipy 库的 Python 中。使用这个精彩的教程http://www.scipy.org/Cookbook/C_Extensions/NumPy_arrays,我很快就采用了 C 函数来从 Python 调用。但是有些 C 函数调用 MatLab 函数,所以我必须通过从 C 代码调用 numpy 和 scipy 函数来替换这段代码。

我尝试过类似Extending and Embedding the Python Interpreter 的操作。但是,我遇到了一个问题:如何将数组传递给函数参数。此外,在模块中查找函数然后为参数构建元组的这种漫长的方法似乎不是很优雅。

那么,例如,如何在 C 代码中调用 numpy 模块中的 sum 函数?

如果有任何想法或链接,我将不胜感激。 鲁本

附:举个例子:

    PyObject *feedback(PyObject *self, PyObject *args)
    PyArrayObject *Vecin;
    double mp=0,ret;
    if( !PyArg_ParseTuple(args,"O!d",&PyArray_Type,&Vecin,&mp)
      ||  Vecin == NULL ) return NULL;
    /* make python string with module name */
    PyObject *pName = PyString_FromString("numpy");
    if( pName == NULL)
        fprintf(stderr,"Couldn\'t setup string %s\n","numpy");
        return NULL;
    
    /* import module */
    PyObject *pModule = PyImport_Import(pName);
    Py_DECREF(pName);
    if( pModule == NULL)
        fprintf(stderr,"Couldn\'t find module %s\n","numpy");
        return NULL;
    
    /* get module dict */
    PyObject *dic = PyModule_GetDict(pModule);
    if( dic == NULL)
        fprintf(stderr,"Couldn\'t find dic in module %s\n","numpy");
        return NULL;
    
    /* find function */
    PyObject *pFunction = PyDict_GetItemString(dic, "sum");
    Py_DECREF(dic);
    if( pFunction == NULL)
        fprintf(stderr,"Couldn\'t find function  %s in dic\n","sum");
        return NULL;
    
    Py_DECREF(pModule);
    /* create typle for new function argument */
    PyObject *inarg = PyTuple_New(1);
    if( inarg == NULL)
        fprintf(stderr,"Cannot convert to Build in Value\n");
        return NULL;
    
    /* set one input paramter */
    PyTuple_SetItem(inarg, 0, (PyObject*)Vecin);
    /* call sunction from module and get result*/
    PyObject *value = PyObject_CallObject(pFunction, inarg);
    if( value == NULL)
        fprintf(stderr,"Function return NULL pointer\n");
        return NULL;
    
    Py_DECREF(pFunction);
    if( !PyArg_ParseTuple(value,"d",&ret) ) return NULL;
    return Py_BuildValue("d",ret*mp);

结果

>>print mymod.FeedBack(np.array([1.,2.,3.,4.,5.]),2)


Traceback (most recent call last):
  File "mymodtest.py", line 10, in <module>
    print mymod.FeedBack(np.array([1.,2.,3.,4.,5.]),2)
SystemError: new style getargs format but argument is not a tuple
Segmentation fault

【问题讨论】:

对你有帮助吗:***.com/a/15670672/1031417 ? @0x90 可能不是。我不使用任何包装器或预翻译器,从 python 到 c,因为 mex 扩展中的原始代码是 c 代码。 是否使用Cython 选项?它对 NumPy 有特殊的支持,并且比 Python C API 更容易使用。 @larsmans。我知道了,谢谢!问题出在为 MatLab 作为 mex 模块编写的 c 代码中。我想保持这段代码完整。 @rth:你可以用 Cython 包装 C 代码。 【参考方案1】:

NumPy C API 有 PyArray_Sum:

PyObject *sum = PyArray_Sum(arr, NPY_MAXDIMS, PyArray_DESCR(arr)->type_num, NULL);

【讨论】:

很好,谢谢。但是 sum-function 只是一个例子。 numpy 和 scipy 中的所有其他函数呢?他们都有C API吗?我真的很困惑,如何用数组为 numpy/scipy 函数形成输入参数元组。 @rth 您可以像使用任何其他 Python 函数一样形成输入参数元组,或者只使用 PyObject_CallFunctionObjArgs @eatmur 我在上面的示例中已将PyObject *value = PyObject_CallObject(pFunction, inarg); 更改为PyObject *value = PyObject_CallFunctionObjArgs(pFunction, Vecin,NULL); 并返回SystemError: new style getargs format but argument is not a tuple Segmentation fault @rth 你希望函数返回一个元组吗? @rth 还有,哪个调用失败了?

以上是关于从 C 代码调用 numpy 函数的主要内容,如果未能解决你的问题,请参考以下文章

如何从 GTK+2 C 代码中调用 matlab/octave 函数

使用 ctypes 从 C 结构数组到 NumPy 数组的高效转换

从汇编代码调用库中的 C 函数

可以直接从 C 代码调用的 ESQL/C 函数?

使用 Eclipse 从 Android 中的 C 代码调用 Java 函数而不调用 Java

LNK2019:从 CPP 代码调用 C 函数