Last active
August 29, 2015 14:01
-
-
Save amirouche/557e762a452278d972d4 to your computer and use it in GitHub Desktop.
create a shared lib to call python code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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