5

I'm trying to move some MatLab code with Mex extensions into Python with numpy and scipy libraries. Using this wonderful tutorial http://www.scipy.org/Cookbook/C_Extensions/NumPy_arrays, I quite quickly adopt C-functions for calling from the Python. But some C-functions call MatLab functions, so I have to substitute this code by calling numpy and scipy functions from C-code.

I've tried to do something like this Extending and Embedding the Python Interpreter. However, I faced the problem: how to pass array into the function argument. Moreover this long way to find function in module and then build tuple for arguments doesn't seems very elegant.

So, how to call sum function in numpy module from C-code, for example?

I'll appreciate for any ideas or links. Ruben

P.S. Here an example:

    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);
}

Result of

>>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
Joel Vroom
  • 1,611
  • 1
  • 16
  • 30
rth
  • 2,946
  • 1
  • 22
  • 27
  • does it help you: http://stackoverflow.com/a/15670672/1031417 ? – 0x90 Apr 18 '13 at 03:41
  • @0x90 probably not. I don't use any wrapper or pretranslators, from python to c, because original code in mex extensions is a c-code. – rth Apr 18 '13 at 03:48
  • Is using [Cython](http://cython.org) an option? It has special support for NumPy and it's much easier to work with than the Python C API. – Fred Foo Apr 18 '13 at 15:18
  • @larsmans. I know, thank you! The problem is in c-code which was written for MatLab as mex module. I'd like to keep this code intact. – rth Apr 18 '13 at 15:54
  • @rth: you can wrap C code with Cython. – Fred Foo Apr 18 '13 at 17:34

1 Answers1

2

The NumPy C API has PyArray_Sum:

PyObject *sum = PyArray_Sum(arr, NPY_MAXDIMS, PyArray_DESCR(arr)->type_num, NULL);
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • It is nice, thank you. But sum-function just an example. What about all other function in numpy and scipy? Do they all have C API? It really puzzles me, how to form input argument tuple for numpy/scipy functions with arrays. – rth Apr 18 '13 at 16:00
  • @rth you form the input argument tuple as you would any other Python function, or just use `PyObject_CallFunctionObjArgs`. – ecatmur Apr 18 '13 at 17:01
  • @eatmur I've changed in my example above from `PyObject *value = PyObject_CallObject(pFunction, inarg);` to `PyObject *value = PyObject_CallFunctionObjArgs(pFunction, Vecin,NULL);` and it returns `SystemError: new style getargs format but argument is not a tuple Segmentation fault` – rth Apr 18 '13 at 18:21
  • @rth are you expecting the function to return a tuple? – ecatmur Apr 18 '13 at 18:51
  • @rth also, which call is failing? – ecatmur Apr 18 '13 at 19:10
  • Oh! I'm fool! :( It returns probably PyFloat or something like this..... Well `PyObject_CallFunctionObjArgs` solves the problem. Thank you! – rth Apr 18 '13 at 19:17