整合Python和C++
我在学习C++,因为它是一种非常灵活的编程语言。不过对于像Twitter、Facebook、Delicious这些互联网应用,Python似乎是个更好的选择。
在同一个项目中把C++和Python结合起来使用,有可能吗?
12 个回答
Python/C API参考手册 - 这是给想用C和C++编程的朋友们准备的手册,帮助他们写扩展模块或者把Python嵌入到其他程序里。
这部分内容讲的是如何用C或C++写模块,以便为Python解释器添加新的功能。这些模块不仅可以定义新的函数,还可以创建新的对象类型和它们的方法。文档还介绍了如何把Python解释器嵌入到其他应用程序中,作为一种扩展语言使用。最后,它还展示了如何编译和链接扩展模块,这样在运行时就可以动态加载这些模块到解释器中,前提是你的操作系统支持这个功能。
是的,这是可能的,而且是被鼓励的,相关的内容也有说明。我自己也做过,发现其实很简单。
把Python和C/C++连接起来可不是件简单的事。
这里我复制了一段之前的回答,讲述了几种编写Python扩展的方法,包括Boost.Python、SWIG、Pybindgen等。
你可以自己用C或C++写一个扩展,使用Python C-API。
简单来说:除了学习怎么做之外,别这么做。这非常难,容易出错。你需要手动管理引用计数,还得写很多代码才能暴露一个函数,收益却很少。
Swig:
优点:可以为很多脚本语言生成绑定。
缺点:我不太喜欢它的解析器工作方式。两年前,C++解析器的功能相当有限。我经常需要复制粘贴我的头文件,添加一些
%
字符,给Swig解析器提供额外的提示。有时候我还得处理Python C-API来进行(不那么)复杂的类型转换。
现在我不再使用它了。
-
优点:这是一个非常完整的库。它几乎可以做C-API能做的所有事情,但用C++来实现。我从来没有用这个库写过C-API代码,也没有遇到过由于库引起的bug。绑定的代码要么运行得很好,要么就编译不通过。
如果你已经有一些C++库需要绑定,这可能是目前最好的解决方案。但如果你只是想重写一个小的C函数,我可能会尝试Cython。
缺点:如果你没有预编译的Boost.Python库,你就得使用Bjam(类似于make的工具)。我真的很讨厌Bjam和它的语法。
用B.P创建的Python库往往会变得很庞大。编译这些库也需要很多时间。
Py++:这是简化版的Boost.Python。Py++使用C++解析器读取你的代码,然后自动生成Boost.Python代码。你还可以得到作者的很好的支持(不是我哦 ;-))。
缺点:只有Boost.Python本身带来的问题。
编辑 这个项目看起来已经停止维护。虽然可能仍然可以使用,但考虑换个方案可能更好。
-
它生成处理C-API的代码。你可以在Python文件中描述函数和类,或者让Pybindgen读取你的头文件并自动生成绑定(为此它使用了pygccxml,这是Py++的作者写的一个Python库)。
缺点:这是一个年轻的项目,团队比Boost.Python小。仍然有一些限制:你不能暴露自己的C++异常,也不能对C++类使用多重继承。
不过值得一试!
Pyrex和Cython:
在这里你不需要写真正的C/C++代码,而是写一种Python和C的混合代码。这个中间代码会生成一个普通的Python模块。
编辑 2013年7月22日:现在Py++看起来已经停止维护,我在寻找一个好的替代品。目前我正在尝试Cython来处理我的C++库。这种语言是Python和C的混合。在Cython函数中,你可以使用Python或C/C++的实体(函数、变量、对象等)。
Cython相对容易学习,性能很好,如果你不需要与旧的C++库接口,甚至可以完全避免使用C/C++。
不过对于C++来说,它也有一些问题。它没有Py++那么“自动化”,所以对于稳定的C++ API(我库现在就是这种情况)可能更好。我觉得Cython最大的问题是C++多态性。用Py++/Boost.Python,我可以在C++中定义一个虚方法,在Python中重写它,并在C++中调用Python版本。用Cython也能做到,但你需要明确使用C-Python API。
编辑 2017年10月6日:
现在有一个新的库,叫做pybind11,类似于Boost.Python,但有一些潜在的优势。例如,它使用C++11的语言特性,使得创建新的绑定更简单。而且它是一个头文件库,所以在使用之前不需要编译,也不需要链接库。
我尝试过一点,确实很简单,使用起来也很愉快。我唯一担心的是,像Boost.Python一样,它可能会导致较长的编译时间和较大的库。我还没有进行任何基准测试。