首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 調用 Python 模塊完全指南:嵌入式 Python API 實戰

     編輯:關於C++

背景

Python 作為膠水語言,C/C++ 可通過 Python.h 嵌入 Python 解釋器,調用 Python 模塊/函數,實現混合編程。

環境配置

  • 頭文件:Python 安裝目錄/include
  • 庫文件:Windows 下 python3x.lib,Linux 下 -lpython3.x
  • 鏈接時需指定上述路徑。

核心 API 流程

  1. Py_Initialize():初始化解釋器。
  2. PyRun_SimpleString("import sys; sys.path.append('...')"):添加模塊搜索路徑。
  3. PyImport_ImportModule("module_name"):加載模塊(返回借用引用)。
  4. PyObject_GetAttrString(module, "func_name"):獲取函數對象。
  5. PyTuple_New(n) + PyTuple_SetItem 構造參數元組,或 Py_BuildValue("(ii)", a, b) 一步構造。
  6. PyObject_CallObject(func, args):調用函數。
  7. PyLong_AsLong(ret) / PyFloat_AsDouble / PyUnicode_AsUTF8 提取返回值。
  8. Py_DECREF(obj):釋放引用(關鍵,防內存洩漏)。
  9. Py_Finalize():關閉解釋器。

完整示例:調用 test.py 中的 test_add(a,b)

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;
}

參數構造與返回值轉換速查表

類型構造參數解析返回值
intPyLong_FromLong(v)PyLong_AsLong(obj)
doublePyFloat_FromDouble(v)PyFloat_AsDouble(obj)
stringPyUnicode_FromString(s)PyUnicode_AsUTF8(obj)
tuplePy_BuildValue("(ii)", a, b)PyArg_ParseTuple(obj, "ii", &a, &b)

注意事項(避坑指南)

  1. 路徑必須正確:sys.path.append 路徑建議用絕對路徑,含中文路徑需注意編碼。
  2. 模塊名 ≠ 文件名:PyImport_ImportModule("test") 導入 test.py,不要加 .py。
  3. 引用計數:Py_DECREF 必須與 Py_INCREF/獲取配對,否則內存洩漏或崩潰。
  4. 錯誤處理:調用失敗時 PyErr_Print() 打印 Python 異常堆棧。
  5. 線程安全:多線程調用需 PyGILState_Ensure/Release 管理 GIL。
  6. Python 版本:Python 3.x 用 PyUnicode,2.x 用 PyString,API 有差異。

總結

C++ 嵌入 Python 適合邏輯層用 C++、算法/腳本層用 Python的架構。關鍵掌握:初始化 → 路徑 → 加載模塊 → 獲取函數 → 構造參數 → 調用 → 解析返回 → 釋放引用 → 終結。引用計數管理是最易出錯環節,建議封裝 RAII 智能指針簡化資源管理。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved