Python 非平凡 C++ 扩展
我有一个比较大的C++库,还有几个支持它的子库,现在我想把整个库变成一个Python扩展。因为需要在不同平台上都能用,所以我选择了distutils这个工具,不过如果有更好的工具,我也愿意听听建议。
请问有没有办法让distutils先编译这些子库,然后在从主库创建扩展的时候把它们链接进来呢?
1 个回答
我在我们的产品中使用了一个庞大的C++库,做的就是这个。市面上有几个工具可以帮助你自动化编写绑定的任务:最受欢迎的就是SWIG,它已经存在很久了,很多项目都在用,通常效果很好。
我觉得SWIG最大的缺点是它自己的C++代码库相当老旧。它是在STL出现之前写的,拥有自己的半动态类型系统,现在看起来有点过时。如果你需要深入修改核心代码(我曾经尝试过将doxygen转换为文档字符串),这可能会让你感到困难。不过,很多人也说SWIG生成的代码效率不高,虽然这可能是真的,但对我来说,我从未觉得SWIG的调用会成为性能瓶颈。
如果你觉得SWIG不合你的口味,还有其他工具可以选择:boost.python也很受欢迎,如果你在C++代码中已经使用了boost库,这可能是个不错的选择。不过,它的缺点是编译时间比较长,因为几乎都是基于C++模板的。
这两个工具都需要你提前做一些工作,定义哪些内容会被暴露,以及具体怎么做。对于SWIG,你需要提供接口文件,这些文件类似于C++的头文件,但简化了,并且有一些额外的指令告诉SWIG如何转换复杂类型等。编写这些接口可能会很繁琐,所以你可以考虑使用pygccxml来帮助你自动生成它们。
这个包的作者实际上还写了另一个扩展,你可能会喜欢:py++。这个包有两个功能:它可以自动生成绑定定义,然后可以传递给boost.python来生成Python绑定:基本上对大多数人来说是一个完整的解决方案。如果你没有特别复杂的需求,可以从这里开始。
还有一些其他问题可能对你有帮助,作为参考:
你也可以查看这个关于Python绑定生成工具的比较,虽然正如Alex在评论中提到的,这个比较有点老旧,但至少能让你对现状有个了解……
至于如何进行构建,你可能想看看比distutils更高级的构建工具:如果你想继续使用Python,我强烈推荐Waf作为框架(其他人会告诉你SCons是更好的选择,但相信我,它慢得要命:我已经经历过了!)……这需要一点学习,但当你掌握后,它非常强大。而且因为它是纯Python的,所以可以完美地与构建过程中你使用的任何其他Python代码集成(比如最后你使用Py++)……