Friday, December 21, 2012

Embedding Python Code in C - The Raspberry Pi Edition

Embedding python code, a.k.a executing python code from code written in C is explained by this notorious Linux Journal article: http://www.linuxjournal.com/article/8497. Actually, there is some explanation regarding the subject in the Extending and Embedding the Python Interpreter section of Python Documentation (mine is Python v2.7.3 documentation).

Let's put the lesson in those source to good use. The target is Raspberry Pi with Debian "Wheezy".

First up, install python-dev package to your Raspberry Pi. This will also install all required packages if they're not yet installed.
sudo apt-get install python-dev
We need the python-dev package to obtain python-config, the C header files and libraries to link out C code with the python interpreter.

After python-dev installed. We need to find what are the GCC linker parameters that we need to use to link to the python interpreter in Raspberry Pi. In many cases this will be different from the linker parameters in your desktop (x86) distro. This is the command to know the GCC linker parameters:
pi@raspberrypi ~/experiments/c_to_python $ python-config  --ldflags
-L/usr/lib/python2.7/config -lpthread -ldl -lutil -lm -lpython2.7 -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions
As you can see, it's pretty long. We're going to need it in our Makefile later.

Now, let's make a very simple C program that invoke the python interpreter and print "hello" to the console from inside the interpreter. This is my code that has been tested and worked:
#include < python2.7/Python.h >
#include < stdio.h >

void exec_pycode(const char* py_code);

int main(int argc, char* argv[])
{

        exec_pycode("print \"hello\"");
        return 0;
}


void exec_pycode(const char* py_code)
{
        Py_Initialize();
        PyRun_SimpleString(py_code);
        Py_Finalize();
}

As you can see, the code is very simple. You will need to use a Makefile to build the application because the linker parameter is quite tedious to input by hand. This is how my Makefile looks like:
# compile c_to_python.c

default:
        gcc -L/usr/lib/python2.7/config -lpthread -ldl -lutil -lm -lpython2.7 -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions -o invoke_python c_to_python.c
The C code in the preceding listing is in the file named c_to_python.c and the output file is named invoke_python. This is the result of the execution:

It's not that hard, isn't it? From this point on, you can experiment with C programs that invokes python code. I have yet to find how to do this in a cross-compilation environment. For now, I have to do all the stuff in my Raspberry Pi (via ssh).


Post a Comment

No comments: