兩種綁定方式選擇
- 無參數/簡單類型:
extern "C" 導出 C 兼容函數,ctypes 直接調用(最簡單)
- 複雜類型/類/重載:SWIG 自動生成綁定代碼(推薦,功能全)
SWIG 完整流程實戰
1. 接口文件 (rachel.i)
%module rachel
%{
#include "rachel.h"
%}
extern int linear(int x, int w, int b);
2. C++ 代碼
// rachel.h
#ifndef RACHEL_H
#define RACHEL_H
int linear(int x, int w, int b);
#endif
// rachel.cpp
#include "rachel.h"
#include
int linear(int x, int w, int b) {
int res = w * x + b;
printf("%d\n", res);
return res;
}
3. 編譯命令
# 1. SWIG 生成包裝代碼
swig -c++ -python rachel.i
# 生成:rachel_wrap.cxx, rachel.py
# 2. 編譯包裝代碼
g++ -c -fPIC rachel_wrap.cxx -I/usr/include/python3.8 -I./include
# 3. 編譯 C++ 實現
g++ -c -fPIC rachel.cpp -I./include
# 4. 鏈接生成動態庫(模塊名稱必須為 _模塊名.so)
g++ -shared rachel.o rachel_wrap.o -o _rachel.so
# Python 3 可能需要:-lpython3.8
4. Python 調用
>>> import _rachel
>>> _rachel.linear(1, 2, 5)
7
>>> # 返回值 7,控制台也輸出 7
進階:類、重載、STL 容器綁定
%module mylib
%{
#include "mylib.h"
%}
// 類綁定
%include "mylib.h"
// 或顯式聲明
%inline %{
class MyClass {
public:
MyClass(int v) : val(v) {}
int getVal() { return val; }
void setVal(int v) { val = v; }
private:
int val;
};
%}
// STL 容器支持
%include
%include
%template(IntVector) std::vector;
%template(StringVector) std::vector;
// 異常處理
%exception {
try { $action }
catch (const std::exception& e) {
PyErr_SetString(PyExc_RuntimeError, e.what());
return NULL;
}
}
關鍵配置細節
-fPIC:位置無關代碼,動態庫必需
-shared:生成共享庫
- 輸出文件名必須為
_模塊名.so(Linux/Mac),Windows 為 _模塊名.pyd
- Python.h 路徑:
python3-config --includes 獲取
- 鏈接 Python 庫:
python3-config --ldflags --embed(嵌入式)或 --ldflags(擴展模塊)
常見問題排查
| 問題 | 原因 | 解決 |
| ImportError: undefined symbol | 缺少符號導出 | 確保 C++ 函數非 static,SWIG 接口正確聲明 |
| ImportError: dynamic module does not define module export function | 模塊初始化函數缺失 | 檢查輸出文件名為 _xxx.so,SWIG 生成的 init 函數名匹配 |
| Segmentation fault | 內存管理錯誤 | 檢查所有權轉移、析構函數、STL 容器內存管理 |
| 類型轉換失敗 | SWIG 類型映射缺失 | 添加 %typemap 或使用 %apply |
替代方案對比