CPPYY
cppyy 非常灵活易用,可以将c/c++代码封装成python可以直接调用的模块,在这中间,用户不需要任何额外的代码
-
Install:
pip install cppyy
-
即时编译c++代码生成python 扩展模块
以下代码在jupyter/ipython中运行:
import cppyy
# 直接在ipython中写c++代码,cppyy会自动编译成python可以调用的模块,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 命名空间,即时生成模块都在这里
vec_dot = cppyy.gbl.vec_dot
# vec_dot 使用了 std::vector 为入口和出口参数
Vector = cppyy.gbl.std.vector
# Vector[typename]() Vector 是一个模板类,需要传入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>)
# 可以转换成list,看到数据
list(vec1), list(vec2)
([1.0, 2.0, 3.0, 4.0], [1.0, 3.0, 2.0, 4.0])
# 调用c++函数vec_dot
vec_ret = vec_dot(vec1, vec2)
list(vec_ret)
[1.0, 6.0, 6.0, 16.0]
总结
- 需要注意的是即时编译的代码,也是即时用的,下次还需要编译,而不要去探究这个代码编译成的库是存在哪里了。
- 当然可以将c++代码保存在一个文件里如vec_dot.cpp, 直接使用cppyy.include("path/to/vec_dot.cpp"), 和上面的方法是一样的
- cppyy.include 一般是导入头文件,配合cppyy.load_libraries 导入动态库,这样可以避免即时编译,头文件只是提供一些接口,使得python知道有哪些模块函数
- 即时编译的技术是利用了cling,由CERN(欧洲原子能组织)为ROOT项目(用于物理实验数据分析/绘图等)开发的
- 如果已经存在一个c++项目,可以使用cmake配合cppyy提供的类似pybind11的功能(但是不需要像pybind11一样来写binding接口),直接将项目生成为python可以调用的模块
参考: