Esto no compila Python al código de la máquina. Pero permite crear una biblioteca compartida para llamar al código Python.
Si lo que está buscando es una manera fácil de ejecutar código Python desde C sin depender de cosas de execp. Podría generar una biblioteca compartida a partir del código de Python envuelto con algunas llamadas a la API de incrustación de Python . Bueno, la aplicación es una biblioteca compartida, un archivo .so que puedes usar en muchas otras bibliotecas / aplicaciones.
Aquí hay un ejemplo simple que crea una biblioteca compartida, que puede vincular con un programa en C. La biblioteca compartida ejecuta el código Python.
El archivo de Python que se ejecutará es 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
Puedes probarlo con python2 -c "import pythoncalledfromc; pythoncalledfromc.main('HELLO')
. Producirá:
python is called from c
string sent by «c» code is:
HELLO
end of «c» code input
La biblioteca compartida se definirá de la siguiente manera callpython.h
:
#ifndef CALL_PYTHON
#define CALL_PYTHON
void callpython_init(void);
int callpython(char ** arguments);
void callpython_finalize(void);
#endif
El asociado callpython.c
es:
// 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();
}
Puedes compilarlo con el siguiente comando:
gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so
Cree un archivo llamado callpythonfromc.c
que contenga lo siguiente:
#include "callpython.h"
int main(void) {
char * example = "HELLO";
callpython_init();
callpython(&example);
callpython_finalize();
return 0;
}
Compílalo y ejecuta:
gcc callpythonfromc.c callpython.so -o callpythonfromc
PYTHONPATH=`pwd` LD_LIBRARY_PATH=`pwd` ./callpythonfromc
Este es un ejemplo muy básico. Puede funcionar, pero dependiendo de la biblioteca, podría ser difícil serializar estructuras de datos C a Python y de Python a C. Las cosas pueden automatizarse de alguna manera ...
Nuitka podría ser útil.
También hay numba, pero ambos no tienen como objetivo hacer exactamente lo que quieres. Es posible generar un encabezado C a partir del código Python, pero solo si especifica cómo convertir los tipos Python a tipos C o puede inferir esa información. Ver python astroid para un analizador Python ast.