CPPYY
cppyy 非常靈活易用,可以將c/c++代碼封裝成python可以直接調(diào)用的模塊,在這中間,用戶不需要任何額外的代碼
-
Install:
pip install cppyy
-
即時(shí)編譯c++代碼生成python 擴(kuò)展模塊
以下代碼在jupyter/ipython中運(yùn)行:
import cppyy
# 直接在ipython中寫c++代碼,cppyy會(huì)自動(dòng)編譯成python可以調(diào)用的模塊,on-the-fly compilation
# 生成的模塊接口和c++中定義的是一致的
cppyy.cppdef("""
std::vector<double> vec_dot(const std::vector<double> &vec1, const std::vector<double> &vec2){
std::vector<double> ret;
if (vec1.size() != vec2.size()) return ret;
int size = vec1.size();
for (int i=0;i<size;i++){
ret.push_back(vec1[i] * vec2[i]);
}
return ret;
}
""")
True
# 使用上面定義的vec_dot
# cppyy.gbl 是global 命名空間,即時(shí)生成模塊都在這里
vec_dot = cppyy.gbl.vec_dot
# vec_dot 使用了 std::vector 為入口和出口參數(shù)
Vector = cppyy.gbl.std.vector
# Vector[typename]() Vector 是一個(gè)模板類,需要傳入tpyenae,但是python中使用[] 而不是<>
vec1 = Vector[float]([1.0, 2.0, 3.0, 4.0])
vec2 = Vector[float]([1.0, 3.0, 2.0, 4.0])
vec1, vec2
(<cppyy.gbl.std.vector<float> object at 0x000001E120E8ECF0>,
<cppyy.gbl.std.vector<float> object at 0x000001E120E8FA70>)
# 可以轉(zhuǎn)換成list,看到數(shù)據(jù)
list(vec1), list(vec2)
([1.0, 2.0, 3.0, 4.0], [1.0, 3.0, 2.0, 4.0])
# 調(diào)用c++函數(shù)vec_dot
vec_ret = vec_dot(vec1, vec2)
list(vec_ret)
[1.0, 6.0, 6.0, 16.0]
總結(jié)
- 需要注意的是即時(shí)編譯的代碼,也是即時(shí)用的,下次還需要編譯,而不要去探究這個(gè)代碼編譯成的庫是存在哪里了。
- 當(dāng)然可以將c++代碼保存在一個(gè)文件里如vec_dot.cpp, 直接使用cppyy.include("path/to/vec_dot.cpp"), 和上面的方法是一樣的
- cppyy.include 一般是導(dǎo)入頭文件,配合cppyy.load_libraries 導(dǎo)入動(dòng)態(tài)庫,這樣可以避免即時(shí)編譯,頭文件只是提供一些接口,使得python知道有哪些模塊函數(shù)
- 即時(shí)編譯的技術(shù)是利用了cling,由CERN(歐洲原子能組織)為ROOT項(xiàng)目(用于物理實(shí)驗(yàn)數(shù)據(jù)分析/繪圖等)開發(fā)的
- 如果已經(jīng)存在一個(gè)c++項(xiàng)目,可以使用cmake配合cppyy提供的類似pybind11的功能(但是不需要像pybind11一樣來寫binding接口),直接將項(xiàng)目生成為python可以調(diào)用的模塊
參考: