To nie kompiluje Pythona do kodu maszynowego. Ale pozwala stworzyć współdzieloną bibliotekę do wywoływania kodu Pythona.
Jeśli szukasz łatwego sposobu na uruchomienie kodu Pythona z poziomu C bez polegania na plikach execp. Możesz wygenerować bibliotekę współdzieloną z kodu Pythona opakowanego w kilka wywołań API osadzania w Pythonie . Cóż, aplikacja jest biblioteką współdzieloną, tak że można jej używać w wielu innych bibliotekach / aplikacjach.
Oto prosty przykład, który tworzy bibliotekę współdzieloną, którą można połączyć z programem C. Biblioteka współdzielona wykonuje kod Pythona.
Plik Pythona, który zostanie wykonany, to pythoncalledfromc.py
:
def main(string):
print "python is called from c"
print "string sent by «c» code is:"
print string
print "end of «c» code input"
return 0xc0c4
Możesz to wypróbować python2 -c "import pythoncalledfromc; pythoncalledfromc.main('HELLO')
. Wyświetli:
python is called from c
string sent by «c» code is:
HELLO
end of «c» code input
Biblioteka współdzielona zostanie zdefiniowana przez callpython.h
:
#ifndef CALL_PYTHON
#define CALL_PYTHON
void callpython_init(void);
int callpython(char ** arguments);
void callpython_finalize(void);
#endif
Powiązane callpython.c
to:
#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();
}
Możesz go skompilować za pomocą następującego polecenia:
gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so
Utwórz plik o nazwie, callpythonfromc.c
który zawiera następujące elementy:
#include "callpython.h"
int main(void) {
char * example = "HELLO";
callpython_init();
callpython(&example);
callpython_finalize();
return 0;
}
Skompiluj i uruchom:
gcc callpythonfromc.c callpython.so -o callpythonfromc
PYTHONPATH=`pwd` LD_LIBRARY_PATH=`pwd` ./callpythonfromc
To jest bardzo podstawowy przykład. Może działać, ale w zależności od biblioteki może być nadal trudno serializować struktury danych C do Pythona iz Pythona do C. Wszystko można nieco zautomatyzować ...
Nuitka może być pomocna.
Jest też numba, ale obaj nie mają na celu robienia dokładnie tego, co chcesz. Generowanie nagłówka C z kodu Pythona jest możliwe, ale tylko wtedy, gdy określisz sposób konwersji typów Python na typy C lub możesz wywnioskować te informacje. Zobacz Python astroid dla analizatora Python ast.