C 語言透過 Python.h 提供的 C API 嵌入 Python 解譯器,實現雙向互動:
call.py# call.py
def test():
print('hello world')
def add(a, b):
return a + b
#include <stdio.h>
#include <stdlib.h>
#include <Python.h>
int main(int argc, char *argv[]) {
/* 1. 初始化 Python 解譯器 */
Py_Initialize();
if (!Py_IsInitialized()) {
fprintf(stderr, "Python 初始化失敗\n");
return -1;
}
/* 2. 將當前目錄加入模組搜尋路徑 */
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
/* 3. 載入模組 */
PyObject *pName = PyUnicode_FromString("call"); // Python 3 使用 PyUnicode
PyObject *pModule = PyImport_Import(pName);
Py_DECREF(pName);
if (!pModule) {
PyErr_Print();
fprintf(stderr, "無法載入 call.py\n");
Py_Finalize();
return -1;
}
/* 4. 取得模組字典 */
PyObject *pDict = PyModule_GetDict(pModule);
if (!pDict) {
Py_DECREF(pModule);
Py_Finalize();
return -1;
}
/* 5. 呼叫無參函數 test() */
PyObject *pFunc = PyDict_GetItemString(pDict, "test");
if (pFunc && PyCallable_Check(pFunc)) {
PyObject_CallObject(pFunc, NULL);
} else {
fprintf(stderr, "找不到函數 test\n");
}
/* 6. 呼叫有參函數 add(3, 4) */
pFunc = PyDict_GetItemString(pDict, "add");
if (pFunc && PyCallable_Check(pFunc)) {
PyObject *pArgs = PyTuple_New(2);
PyTuple_SetItem(pArgs, 0, PyLong_FromLong(3)); // Python 3 用 PyLong
PyTuple_SetItem(pArgs, 1, PyLong_FromLong(4));
PyObject *pResult = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pArgs);
if (pResult) {
long ret = PyLong_AsLong(pResult); // Python 3 用 PyLong_AsLong
printf("add result: %ld\n", ret);
Py_DECREF(pResult);
}
} else {
fprintf(stderr, "找不到函數 add\n");
}
/* 7. 清理與關閉 */
Py_DECREF(pDict);
Py_DECREF(pModule);
Py_Finalize();
return 0;
}
| 功能 | Python 2 | Python 3 |
|---|---|---|
| 字串建構 | PyString_FromString | PyUnicode_FromString |
| 整數建構 | PyInt_FromLong | PyLong_FromLong |
| 整數解析 | PyInt_AsLong | PyLong_AsLong |
| 模組名稱 | PyString_FromString | PyUnicode_FromString |
# Linux/macOS (Python 3.8+)
gcc -o embed embed.c $(python3-config --cflags --ldflags)
# 或手動指定
gcc -o embed embed.c -I/usr/include/python3.8 -lpython3.8
sys.path、模組檔名、__pycache__ 干擾Py_DECREF 漏/重)PyErr_Print() 印出 Python 例外堆疊Py_BuildValue 格式字串速查"i" - int
"l" - long
"d" - double
"s" - char* (UTF-8)
"O" - PyObject* (傳遞既有物件)
"(ii)" - 兩個 int 組成的 tuple
"[ii]" - 兩個 int 組成的 list
"{s:i, s:i}" - dict
Py_BuildValue 簡化參數建構/* 替代 PyTuple_New + PyTuple_SetItem 系列 */
PyObject *pArgs = Py_BuildValue("(ll)", 3, 4); // 直接建構 (3, 4) tuple
PyObject *pResult = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pArgs);