Điều này không biên dịch Python thành mã máy. Nhưng cho phép tạo một thư viện chia sẻ để gọi mã Python.
Nếu những gì bạn đang tìm kiếm là một cách dễ dàng để chạy mã Python từ C mà không cần dựa vào công cụ thực thi. Bạn có thể tạo một thư viện chia sẻ từ mã python được gói bằng một vài lệnh gọi tới API nhúng Python . Ứng dụng này là một thư viện dùng chung, một .so mà bạn có thể sử dụng trong nhiều thư viện / ứng dụng khác.
Dưới đây là một ví dụ đơn giản tạo thư viện dùng chung, bạn có thể liên kết với chương trình C. Thư viện chia sẻ thực thi mã Python.
Tệp python sẽ được thực thi là 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
Bạn có thể thử nó với python2 -c "import pythoncalledfromc; pythoncalledfromc.main('HELLO')
. Nó sẽ xuất ra:
python is called from c
string sent by «c» code is:
HELLO
end of «c» code input
Thư viện dùng chung sẽ được xác định bởi các mục sau callpython.h
:
#ifndef CALL_PYTHON
#define CALL_PYTHON
void callpython_init(void);
int callpython(char ** arguments);
void callpython_finalize(void);
#endif
Liên kết callpython.c
là:
// 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();
}
Bạn có thể biên dịch nó bằng lệnh sau:
gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so
Tạo một tệp có tên callpythonfromc.c
như sau:
#include "callpython.h"
int main(void) {
char * example = "HELLO";
callpython_init();
callpython(&example);
callpython_finalize();
return 0;
}
Biên dịch nó và chạy:
gcc callpythonfromc.c callpython.so -o callpythonfromc
PYTHONPATH=`pwd` LD_LIBRARY_PATH=`pwd` ./callpythonfromc
Đây là một ví dụ rất cơ bản. Nó có thể hoạt động, nhưng tùy thuộc vào thư viện, có thể vẫn khó sắp xếp các cấu trúc dữ liệu C thành Python và từ Python sang C. Mọi thứ có thể được tự động hóa phần nào ...
Nuitka có thể hữu ích.
Ngoài ra còn có numba nhưng cả hai đều không nhằm mục đích làm chính xác những gì bạn muốn. Có thể tạo tiêu đề C từ mã Python, nhưng chỉ khi bạn chỉ định cách chuyển đổi loại Python thành loại C hoặc có thể suy ra thông tin đó. Xem python astroid cho một phân tích ast ast Python.