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/

10 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. This comment has been removed by a blog administrator.

    ReplyDelete
  4. 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
  5. I’ve bookmarked your site, and I’m adding your RSS feeds to my Google account.

    selenium training in bangalore|

    ReplyDelete
  6. Thanks for sharing this post. Your post is really very helpful its students.

    python training in chennai

    selenium training in chennai

    ReplyDelete
  7. This comment has been removed by a blog administrator.

    ReplyDelete