Python 作為膠水語言,C/C++ 可通過 Python.h 嵌入 Python 解釋器,調用 Python 模塊/函數,實現混合編程。
Python 安裝目錄/includepython3x.lib,Linux 下 -lpython3.xPy_Initialize():初始化解釋器。PyRun_SimpleString("import sys; sys.path.append('...')"):添加模塊搜索路徑。PyImport_ImportModule("module_name"):加載模塊(返回借用引用)。PyObject_GetAttrString(module, "func_name"):獲取函數對象。PyTuple_New(n) + PyTuple_SetItem 構造參數元組,或 Py_BuildValue("(ii)", a, b) 一步構造。PyObject_CallObject(func, args):調用函數。PyLong_AsLong(ret) / PyFloat_AsDouble / PyUnicode_AsUTF8 提取返回值。Py_DECREF(obj):釋放引用(關鍵,防內存洩漏)。Py_Finalize():關閉解釋器。test.py:
def test_add(a, b):
print('add', a, 'and', b)
return a + b
C++ 調用代碼:
#include
#include
#include
using namespace std;
int main() {
Py_Initialize();
if (!Py_IsInitialized()) {
cerr << "Python init failed\n";
return 1;
}
// 設置模塊路徑
string path = "~/test"; // 替換為實際路徑
string cmd = "import sys; sys.path.append(r\"" + path + "\")";
PyRun_SimpleString("import sys");
PyRun_SimpleString(cmd.c_str());
// 加載模塊
PyObject* pModule = PyImport_ImportModule("test"); // 模塊名,非文件名
if (!pModule) {
PyErr_Print();
cerr << "Load module failed\n";
Py_Finalize();
return 1;
}
cout << "Module loaded\n";
// 獲取函數
PyObject* pFunc = PyObject_GetAttrString(pModule, "test_add");
if (!pFunc || !PyCallable_Check(pFunc)) {
cerr << "Function not found\n";
Py_DECREF(pModule);
Py_Finalize();
return 1;
}
cout << "Function got\n";
// 構造參數:(4, 3)
PyObject* pArgs = Py_BuildValue("(ii)", 4, 3);
// 調用
PyObject* pRet = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pArgs);
if (pRet) {
long result = PyLong_AsLong(pRet);
cout << "Result: " << result << endl; // 7
Py_DECREF(pRet);
} else {
PyErr_Print();
}
Py_DECREF(pFunc);
Py_DECREF(pModule);
Py_Finalize();
return 0;
}
| 類型 | 構造參數 | 解析返回值 |
|---|---|---|
| int | PyLong_FromLong(v) | PyLong_AsLong(obj) |
| double | PyFloat_FromDouble(v) | PyFloat_AsDouble(obj) |
| string | PyUnicode_FromString(s) | PyUnicode_AsUTF8(obj) |
| tuple | Py_BuildValue("(ii)", a, b) | PyArg_ParseTuple(obj, "ii", &a, &b) |
sys.path.append 路徑建議用絕對路徑,含中文路徑需注意編碼。PyImport_ImportModule("test") 導入 test.py,不要加 .py。Py_DECREF 必須與 Py_INCREF/獲取配對,否則內存洩漏或崩潰。PyErr_Print() 打印 Python 異常堆棧。PyGILState_Ensure/Release 管理 GIL。PyUnicode,2.x 用 PyString,API 有差異。C++ 嵌入 Python 適合邏輯層用 C++、算法/腳本層用 Python的架構。關鍵掌握:初始化 → 路徑 → 加載模塊 → 獲取函數 → 構造參數 → 調用 → 解析返回 → 釋放引用 → 終結。引用計數管理是最易出錯環節,建議封裝 RAII 智能指針簡化資源管理。