Python作为一门胶水语言,它与C/C++之间的兼容性(Interoperability)我认为是它相比其他动态语言脱颖而出的最大原因。Python原生支持的是与C语言的接口,Python的发行版自带有Python.h头文件,里面提供了在C中调用Python和反过来在Python中调用C的接口定义。但是C++就不一样了,虽然C++ ⇔ C ⇔ Python的通道是可行的,但是想要完整兼容C++的特性的话需要很多额外的重复代码(boilerplate)。因此相应针对Python/C++绑定的库也就应运而生了,我所了解的库主要有四个:Boost.Python,Cython,pybind11,SWIG。
总的来说,Boost.Python和pybind11主要用于给现有C++代码提供Python绑定,并且不用学习新的语法;SWIG提供一个给C++代码编写多种语言绑定的框架,它本质上是一种代码生成器,基于SWIG自定义的语法;Cython则是基于Python的C/C++代码封装器,其本质也是代码生成器,但是Cython的语法是Python的超集,也就是说Python的代码可以零成本移植到Cython中。
Boost.Python是一个Boost框架中封装C++代码的工具,通过宏定义和元编程来简化Python的API调用,消灭bolierplate。Boost.Python还提供对Numpy底层API的封装,因此适用性很强,能满足Python绑定的绝大多数需求。而pybind11则是受Boost.Python启发的一套类似的API,其目标是提供Header-only的易用的Python接口。由于pybind11脱胎于Boost,因此它们的接口非常相似,
Boost.Python/pybind11 vs Cython
这两者的选用其实差别非常大,因为他们的代码逻辑都是不同的。而具体选择哪个库就纯粹是根据需求出发了。他们的区别如下(以下pybind11同时也代表了Boost.Python)
pybind11基于C++,更适合C++工程师。Cython则是基于Python,写习惯的Python的人上手更快,并且能同时方便地兼容Python和C++。
Cython相比pybind11的环境配置更加简单,用户只需通过pip安装Cython就可以利用Cython的功能了,也无需配置路径。
Cython封装C++类会比Boost.Python更加繁杂,你需要先定义C++类,再封装成Python类。相当于Cython还多一步翻译头文件的工作。
Cython支持模板(虽然是阉割版本)!这是Cython独家的一个killer特性,不过是与第3点相关联的。如果你已经翻译好了现有的模板代码,那么用户就可以用Python的语法来自行展开模板了!pybind11需要在编译的时候实例化模板,因此一般只封装常用的实例,或者穷举所有实例化可能(这会导致生成的封装库尺寸爆炸)
pybind11封装重载函数比Cython要方便太多!Cython封装重载函数的话一般需要定义大量的可选参数和类型判断。
Cython封装继承类就更加麻烦了,不仅要处理方法重载,还要复制继承关系,十分繁复。
Cython无法利用上C++的宏定义,这对支持条件编译非常不利,很多时候还需要自己利用Cython的条件语句翻译一套条件编译的逻辑。
Cython似乎在封装上比pybind11性能好,参见pybind11#1227和pybind#2005。如果你的代码需要经常调用封装后的函数,那么选择Cython性能更好。
SWIG
SWIG是个很神奇的东西,他能够将C++代码封装成Python/C#/Java/Ruby等多种语言,但是也正因为这个灵活性,它对C++的高级特性的支持就比较辣鸡了。在CGAL官方的绑定库中可以看到有不少代码需要针对Python和Java打补丁,因此如果没有多语言的需求的话SWIG应该是下下策了。这应该也是SWIG一直没啥发展的原因吧~
简而言之,选择Cython的情况有以下几种需要保留模板参数,让用户可以自行选择用什么类型展开,或者目标用户有继续使用和拓展C++ API的需求有大量的封装函数调用时,Cython的性能最好绑定的对象是C语言写的,那么用Cython封装会更快而选择SWIG只有在你需要同时生成多个语言的绑定的时候推荐使用,其他情况无脑选择pybind11即可。
网友评价:
用过cython和pybind11,就这两者而言,pybind11的体验超好,推荐!
Tensorflow已经从SWIG切到pybind11了
个人比较喜欢/偏向于pybind11,有以下几个原因1. 灵活性:pybind11本质上还是在C API外面包了一层C++(或者说利用C++的元编程能力批量产生binding)所以可定制性很好,尤其是面向我这种有非主流需求的用户。2. 抽象能力:cython这种Python的补丁抽象能力没有完整的C++好,对于一个倾向于只让Python成为傻瓜式接口的人,我更希望能够同时在C++层面有丰富的抽象来方便developer。3. 生态:pybind11现在有很多基于它的生态,例如xtensor,Python/C++里最好的多维数组没有之一。然后还有pythran这个transpiler,可以把Python的prototype转到C++,一定程度上减轻编写C++的蛋疼点。PS. 我觉得有了pythran以后cython已经没有任何优势了。
cython就算了,大清都忘了swig自动化程度特别高,include头文件即可,封装做的好,而且可以同时产出lua等接口pybind11灵活性更高,手撸接口比较方便如果需要产出多种脚本语言的binding、需要导出的接口比较多、或者希望自动化完成尽量使用swig,否则请选择pybind11
我的结论就是使用pybind11,
标签:Cython,封装,Python,SWIG,C++,pybind11,Boost From: https://www.cnblogs.com/andy0816/p/17161559.html