Python Forum

Full Version: Send array of doubles to Python from C and back
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I would like to send an array of double to C to perform an optimization problem in python. The code is as follows:

**mathHelper.py**
    import sys
    from numpy import *
    
    def addVector(a):
        c = 2*a
        return c 
The C code is as follows:

**runMe.c**
    #include </usr/include/python2.7/Python.h>
    #include <stdlib.h>
    #include <string.h>
    #include <numpy/arrayobject.h>

    int main(int argc, char *argv[])
    {
    PyObject *pName, *pModule, *pDict, *pFunc;
    PyObject *pArgs, *pValue, *pVec;

    Py_Initialize();

    // this macro is defined by NumPy and must be included
    import_array(); 
   
    int nLenslet;
    double* h_slopes;
    h_slopes = (double *)malloc( nLenslet * sizeof(double));
    for (int i = 0; i < nLenslet; i++){
       	h_slopes[i] = i;
    }
    npy_double data_slopes[nLenslet];
    pVec = PyArray_SimpleNewFromData( nLenslet, data_slopes, NPY_DOUBLE, h_slopes );
    if (pVec == NULL) printf("There is a problem.\n");
            
    // load the python file
    PyObject *pval;
    PySys_SetPath("/home/roger/Desktop/PythonInC");  // path to the module to import
    char *fileID = "mathHelper"; 
    pName = PyString_FromString(fileID); 
    pModule = PyImport_Import(pName);

    char *functionID = "addVector"; 
    
    if (pModule != NULL) {
    	pFunc = PyObject_GetAttrString(pModule, functionID);
        if (pFunc && PyCallable_Check(pFunc)) {
            pValue = PyObject_CallFunction(pFunc, pVec);
            if (pValue != NULL) {
                printf("Value returned from the function %s", PyString_AsString(pValue));
            } else {
                PyErr_Print();
            }
        } else {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function \"%s\"\n", functionID);
        }
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load file\n");
        return 1;
    }
    free(h_slopes);
    
    }
It is compiled using

    gcc -o final runMe.c -lpython2.7 -std=c99
However, I get the following error message:

>> There is a problem.
>> TypeError: addVector() takes exactly 1 argument (0 given)

Can anyone help me out here? Thanks,
Hi,

Could you kindly put python tags around your code - This link should explain all the detailsĀ PythonTags

Hopefully someone can then help you with your query.

Bass
Hi Bass,

It is now locked and I cannot modify it anymore.
Hi,

It looks like you are trying to call addVector() without passing the function a value. The errmsg is saying that it needs one value/argument and you are not sending it any.

So if the function is to double a number (for example) then it would need to have the number that you wish to double, passed to it in the first place. If you do not pass a number then it would return an errmsg (as it has done) stating that it was expecting a number, and therefore could not double a number if it does not know what the original number was in the first place.

You may need to also check where it calls the function (addVector) as a variable, i.e. check all situations where addVector() is called as well as situations where it is called as functionID rather than addVector.

Does this help?

Bass
Bass - he is talking about the C double data type, not doubling a number
Baptiste - We'd be glad to look at your code if:
  • You re-post within code tags (see BBCODE)
  • fix indentation (paste with Shift-ctrl-V)
Thank you for your answer, it is indeed much easier to read! I got some progress, namely that I can get in the Python function work, and get a PyObj without compiling error.
I do not know how to read the pValue that is sent back to C when it is an array in double. I am still digging but if you have an idea, do not hesitate :)

#include </usr/include/python2.7/Python.h>
#include <stdlib.h>
#include <string.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <numpy/arrayobject.h>


int main(int argc, char *argv[])
{
    PyObject *pName, *pModule, *pFunc, *pValue, *pVec;
    Py_Initialize();

    import_array1(-1); 
    
    int n = 10;
    double *h_slopes, *h_result;
    h_slopes = (double *)malloc( n * sizeof(double));
    h_result = (double *)malloc( n * sizeof(double));
    npy_intp dim[] = {n};
    for (int i = 0; i < n; i++) h_slopes[i] = i;
    npy_double data_slopes[n];
    pVec = PyArray_SimpleNewFromData( 1, dim, NPY_DOUBLE, h_slopes );
    if (pVec == NULL) printf("Cannot fill pVec.\n");
        
    // load mathHelper.py
    PySys_SetPath("/home/roger/Desktop/Python2C");  // path to the module to import
    char *fileID = "mathHelper"; 
    pName = PyString_FromString(fileID); 
    pModule = PyImport_Import(pName);

    char *functionID = "addVector"; 
    
    if (pModule != NULL) {
    	pFunc = PyObject_GetAttrString(pModule, functionID);
        if (pFunc && PyCallable_Check(pFunc)) {
            pValue = PyObject_CallFunction(pFunc, "O", pVec);
            if (pValue != NULL) {
            	//h_result = pValue;
            	
            } else {
                PyErr_Print();
            }
        } else {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function \"%s\"\n", functionID);
        }
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load file\n");
        return 1;
    }
    free(h_slopes);
    free(h_result);
}
Bass - Please do not send PM's the purpose of the forum is to share.
Is it a good idea to transform into a PyArray from the PyObj to then access the elements using PyArray_GetPtr?
Here is what I tried:

pValue = PyObject_CallFunction(pFunc, "O", pVec); 
PyArray_Descr *dtype = NULL;
int ndim = 0;
npy_intp dim2 = {n};
PyArrayObject *aVec;
if (PyArray_GetArrayParamsFromObject(pValue, NULL, 1, &dtype, &ndim, &dim2, &aVec, NULL) != 0) {
    printf("Failed to convert PyObj to PyArray");
}
if (aVec != NULL) {
     if (PyArray_Check(aVec) == 1) {
          int m = PyArray_NDIM(aVec);
          printf("Dimension of array: %i\n",m);
          h_result = PyArray_GetPtr(aVec, dim);
          printf("Check results: \n");
          for (int i = 0; i < 10; i++)
          {
            	printf("%f\n",h_result[i]);
          }
     }  
It compiles without error nor warnings using the same command line as shown in the previous posts. The vector but I get the following output:
Output:
Dimension of array: 1 Check results: 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -nan
instead of the correct values, i.e [0 2 4 6 8 10 12 ... 18]
Hi, I am currently having the PyArray_SimpleNewFromData not declared within the scope error. Could anyone kindly suggest what is being wrong? Thanks!