Python Forum
Send array of doubles to Python from C and back
Thread Rating:
  • 1 Vote(s) - 2 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Send array of doubles to Python from C and back
#1
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,
Reply
#2
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

"The good thing about standards is that you have so many to choose from" Andy S. Tanenbaum
Reply
#3
Hi Bass,

It is now locked and I cannot modify it anymore.
Reply
#4
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

"The good thing about standards is that you have so many to choose from" Andy S. Tanenbaum
Reply
#5
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)
Reply
#6
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);
}
Reply
#7
Bass - Please do not send PM's the purpose of the forum is to share.
Reply
#8
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]
Reply
#9
Hi, I am currently having the PyArray_SimpleNewFromData not declared within the scope error. Could anyone kindly suggest what is being wrong? Thanks!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  save 2d array to file and load back ian 3 18,262 May-18-2018, 05:00 AM
Last Post: scidam

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020