这不会将 Python 编译为机器码。但允许创建一个共享库来调用 Python 代码。
如果您正在寻找一种从 C 语言运行 Python 代码而不依赖 execp 的简单方法。您可以通过对Python embedding API 的几次调用包装的python 代码生成一个共享库。好吧,该应用程序是一个共享库,一个 .so 您可以在许多其他库/应用程序中使用。
这是一个创建共享库的简单示例,您可以将其与 C 程序链接。共享库执行 Python 代码。
要执行的python文件是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
您可以使用python2 -c "import pythoncalledfromc; pythoncalledfromc.main('HELLO') 进行尝试。它将输出:
python is called from c
string sent by «c» code is:
HELLO
end of «c» code input
共享库将由callpython.h定义如下:
#ifndef CALL_PYTHON
#define CALL_PYTHON
void callpython_init(void);
int callpython(char ** arguments);
void callpython_finalize(void);
#endif
关联的callpython.c是:
// 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();
}
你可以用下面的命令编译它:
gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so
创建一个名为 callpythonfromc.c 的文件,其中包含以下内容:
#include "callpython.h"
int main(void) {
char * example = "HELLO";
callpython_init();
callpython(&example);
callpython_finalize();
return 0;
}
编译并运行:
gcc callpythonfromc.c callpython.so -o callpythonfromc
PYTHONPATH=`pwd` LD_LIBRARY_PATH=`pwd` ./callpythonfromc
这是一个非常基本的例子。它可以工作,但根据库的不同,将 C 数据结构序列化为 Python 以及从 Python 序列化为 C 可能仍然很困难。事情可以在某种程度上自动化......
Nuitka 可能会有所帮助。
还有numba,但他们都不打算完全按照您的意愿行事。从 Python 代码生成 C 标头是可能的,但前提是您指定如何将 Python 类型转换为 C 类型或可以推断该信息。有关 Python ast 分析器的信息,请参阅 python astroid。