Saturday, 31 August 2013

How To Pass A C Array To Python Solution

While I commonly use C or C++ for processing signals there are not too many options available for displaying the results graphically so I have been looking at using Matplotlib for the display. The first problem I encountered is how to pass an array of floating point data from C to Python.
There are several options and a lot of forum discussions on the subject but I couldn't find a simple solution. So here is one that I developed earlier.
This example works with an Anaconda/Python v3.3 installation with the 64 bit Microsoft compiler.

See here for an introduction to  Anaconda/Python v3.3 installation and calling Python from the 64 bit Microsoft compiler : http://realgonegeek.blogspot.co.uk/2013/08/how-to-embed-python-pylab-into-64bit.html.

Here is the C code :

#include <Python.h>
#include <stdio.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include "C:\Anaconda\envs\py33\Lib\site-packages\numpy\core\include\numpy\arrayobject.h"

double Array [] = {1.2, 3.4, 5.6, 7.8};

int main (int argc, char *argv[])
{
    PyObject *pName, *pModule, *pDict, *pFunc, *pArgs, *pValue;
    npy_intp dims[1] = { 4 };
    PyObject *py_array;

    Py_Initialize ();
    pName = PyUnicode_FromString ("PrintArray");
    // PyUnicode_FromString error checking here

    pModule = PyImport_Import (pName);                  // Load the module object
    // PyImport_Import error checking here
    Py_DECREF(pName);

    pFunc = PyObject_GetAttrString (pModule, "PrintArray");        // pFunc is a new reference
    // PyObject_GetAttrString error checking here

    import_array ();                                    // Required for the C-API : http://docs.scipy.org/doc/numpy/reference/c-api.array.html#importing-the-api

    py_array = PyArray_SimpleNewFromData (1, dims, NPY_DOUBLE, Array);
    // PyArray_SimpleNewFromData error checking here

    pDict = PyModule_GetDict (pModule);                 // pDict is a borrowed reference

    pArgs = PyTuple_New (1);
    PyTuple_SetItem (pArgs, 0, py_array);

    pFunc = PyDict_GetItemString (pDict, "PrintArray"); // pFunc is also a borrowed reference

    if (PyCallable_Check (pFunc)) 
    {
        PyObject_CallObject (pFunc, pArgs);
    } else 
    {
        printf ("Function not callable !\n");
    }

    Py_DECREF (py_array);                               // Clean up
    Py_DECREF (pModule);
    Py_DECREF (pDict);
    Py_DECREF (pFunc);

    Py_Finalize ();                                     // Finish the Python Interpreter

    return 0;
}

Here is the python script to print the contents of the array :

def PrintArray (a):
    print ("Contents of a :")
    print (a)
    c = 0
    return c

If you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.
Numerix-DSP Libraries : http://www.numerix-dsp.com/eval/

7 comments:

  1. Thanks for the code

    the Py_DECREF(pDict); line gives

    Unhandled exception at 0x1E0ABA42 (python27.dll) in pythonEmbedded2.exe: 0xC0000005: Access violation reading location 0xFEEEFEF2.

    when I comment it out, it works fine.

    Any ideas as to why this is ?

    ReplyDelete
  2. Hi Asanka,
    No, I don't know why this occurs. I use Anaconda and it works fine.
    I'm glad it works for you when you remove the line.
    All the best,
    John

    ReplyDelete
  3. Hi John,

    THANKS FOR THE SOLUTION
    I have two doubts,
    1) How to get the array from python and use those array values in C
    2) Do we need to specify the size of the array in C. How to achieve the Dynamic memory allocation using your code.

    ReplyDelete
    Replies
    1. Hi Reji,
      Unfortunately, I did not need to get data back from Python to C so I have not tried it. If I get a chance I will work something out and upload it.
      Another option would be the SWIG API, I think this should do it.
      Yes, you could malloc Array in the C code although for the example I just created a fixed size array.
      John

      Delete
    2. It works great, thank you very much indeed! Have you found a way to get the array back from the python function?

      Delete
    3. Thank you for your comment. Unfortunately I did not need to get data back to C so I did not work that out.
      If you do find a solution then feel free to add a link to the thread.

      Good luck

      Delete
  4. This is the accurate description of my experience with them as well. The made learning brand marketing very fun and ear for me. It really helped me a lot, especially as I'm just starting my new business. business people

    ReplyDelete