Skip to content

Instantly share code, notes, and snippets.

@amirouche
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amirouche/557e762a452278d972d4 to your computer and use it in GitHub Desktop.
Save amirouche/557e762a452278d972d4 to your computer and use it in GitHub Desktop.
create a shared lib to call python code
This doesn't compile Python to machine code. But allows to create a shared library to call Python code.
If what you are looking for is an easy way to run Python code from C without relying on execp stuff. You could generate a shared library from python code wrapped with a few calls to [Python embedding API][1]. Well the application is a shared library, an .so that you can use in many other libraries/applications.
Here is a simple example which create a shared library, that you can link with a C program. The shared library executes Python code.
The python file that will be executed is `pythoncalledfromc.py`:
# -*- encoding:utf-8 -*-
# this file must be named "pythoncalledfrom.py"
def main(string): # args must a string
print "python is called from c"
print "string sent by «c» code is:"
print string
print "end of «c» code input"
return 0xc0c4 # return something
You can try it with `python2 -c "import pythoncalledfromc; pythoncalledfromc.main('HELLO')`. It will output:
python is called from c
string sent by «c» code is:
HELLO
end of «c» code input
The shared library will be defined by the following by `callpython.h`:
#ifndef CALL_PYTHON
#define CALL_PYTHON
void callpython_init(void);
int callpython(char ** arguments);
void callpython_finalize(void);
#endif
The associated `callpython.c` is:
// gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <python2.7/Python.h>
#include "callpython.h"
#define PYTHON_EXEC_STRING_LENGTH 52
#define PYTHON_EXEC_STRING "import pythoncalledfromc; pythoncalledfromc.main(\"%s\")"
void callpython_init(void) {
Py_Initialize();
}
int callpython(char ** arguments) {
int arguments_string_size = (int) strlen(*arguments);
char * python_script_to_execute = malloc(arguments_string_size + PYTHON_EXEC_STRING_LENGTH);
PyObject *__main__, *locals;
PyObject * result = NULL;
if (python_script_to_execute == NULL)
return -1;
__main__ = PyImport_AddModule("__main__");
if (__main__ == NULL)
return -1;
locals = PyModule_GetDict(__main__);
sprintf(python_script_to_execute, PYTHON_EXEC_STRING, *arguments);
result = PyRun_String(python_script_to_execute, Py_file_input, locals, locals);
if(result == NULL)
return -1;
return 0;
}
void callpython_finalize(void) {
Py_Finalize();
}
You can compile it with the following command:
gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so
Create a file named `callpythonfromc.c` that contains the following:
#include "callpython.h"
int main(void) {
char * example = "HELLO";
callpython_init();
callpython(&example);
callpython_finalize();
return 0;
}
Compile it and run:
gcc callpythonfromc.c callpython.so -o callpythonfromc
PYTHONPATH=`pwd` LD_LIBRARY_PATH=`pwd` ./callpythonfromc
This is a very basic example. It can work, but depending on the library it might be still difficult to serialize C data structures to Python and from Python to C. Things can be automated somewhat...
[Nuitka][2] might be helpful.
Also there is [numba][3] but they both don't aim to do what you want exactly. Generating a C header from Python code is possible, but only if you specify the how to convert the Python types to C types or can infer that information. See [python astroid][4] for a Python ast analyzer.
[1]: https://docs.python.org/2.7/c-api/intro.html#embedding-python
[2]: http://stackoverflow.com/questions/138521/is-it-feasible-to-compile-python-to-machine-code/23596973#23596973
[3]: http://numba.pydata.org/
[4]: https://bitbucket.org/logilab/astroid
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment