如何实现 C/C++ 与 Python 的通信
2016-07-10
展开全部
用C/C++对脚本语言的功能扩展是非常常见的事情,Python也不例外。除了SWIG,市面上还有若干用于Python扩展的工具包,比较知名的还有Boost.Python、SIP等,此外,Cython由于可以直接集成C/C++代码,并方便的生成Python模块,故也可以完成扩展Python的任务。答主在这里选用SWIG的一个重要原因是,它不仅可以用于Python,也可以用于其他语言。如今SWIG已经支持C/C++的好基友Java,主流脚本语言Python、Perl、Ruby、PHP、JavaScript、tcl、Lua,还有Go、C#,以及R。SWIG是基于配置的,也就是说,原则上一套配置改变不同的编译方法就能适用各种语言(当然,这是理想情况了……)SWIG的安装方便,有Windows的预编译包,解压即用,绿色健康。主流Linux通常集成swig的包,也可以下载源代码自己编译,SWIG非常小巧,通常安装不会出什么问题。用SWIG扩展Python,你需要有一个待扩展的C/C++库。这个库有可能是你自己写的,也有可能是某个项目提供的。这里举一个不浮夸的例子:希望在Python中用到SSE4指令集的CRC32指令。首先打开指令集的文档可以看到有6个函数。分析6个函数的原型,其参数和返回值都是简单的整数。于是书写SWIG的配置文件(为了简化起见,未包含2个64位函数):/*File:mymodule.i*/%modulemymodule%{#include"nmmintrin.h"%}int_mm_popcnt_u32(unsignedintv);unsignedint_mm_crc32_u8(unsignedintcrc,unsignedcharv);unsignedint_mm_crc32_u16(unsignedintcrc,unsignedshortv);unsignedint_mm_crc32_u32(unsignedintcrc,unsignedintv);接下来使用SWIG将这个配置文件编译为所谓PythonModuleWrapperswig-pythonmymodule.i得到一个mymodule_wrap.c和一个mymodule.py。把它编译为Python扩展:Windows:cl/LDmymodule_wrap.c/o_mymodule.pyd-IC:\Python27\includeC:\Python27\libs\python27.libLinux:gcc-fPIC-sharedmymodule_wrap.c-o_mymodule.so-I/usr/include/python2.7/-lpython2.7注意输出文件名前面要加一个下划线。现在可以立即在Python下使用这个module了:>>>importmymodule>>>mymodule._mm_popcnt_u32(10)2回顾这个配置文件分为3个部分:定义module名称mymodule,通常,module名称要和文件名保持一致。%{%}包裹的部分是C语言的代码,这段代码会原封不动的复制到mymodule_wrap.c欲导出的函数签名列表。直接从头文件里复制过来即可。还记得本文第2节的那个great_function吗?有了SWIG,事情就会变得如此简单:/*great_module.i*/%modulegreat_module%{intgreat_function(inta){returna+1;}%}intgreat_function(inta);换句话说,SWIG自动完成了诸如Python类型转换、module初始化、导出代码表生成的诸多工作。对于C++,SWIG也可以应对。例如以下代码有C++类的定义://great_class.h#ifndefGREAT_CLASS#defineGREAT_CLASSclassGreat{private:ints;public:voidsetWall(int_s){s=_s;};intgetWall(){returns;};};#endif//GREAT_CLASS对应的SWIG配置文件/*great_class.i*/%modulegreat_class%{#include"great_class.h"%}%include"great_class.h"这里不再重新敲一遍class的定义了,直接使用SWIG的%include指令SWIG编译时要加-c++这个选项,生成的扩展名为cxxswig-c++-pythongreat_class.iWindows下编译:cl/LDgreat_class_wrap.cxx/o_great_class.pyd-IC:\Python27\includeC:\Python27\libs\python27.libLinux,使用C++的编译器g++-fPIC-sharedgreat_class_wrap.cxx-o_great_class.so-I/usr/include/python2.7/-lpython2.7在Python交互模式下测试:>>>importgreat_class>>>c=great_class.Great()>>>c.setWall(5)>>>c.getWall()5也就是说C++的class会直接映射到PythonclassSWIG非常强大,对于Python接口而言,简单类型,甚至指针,都无需人工干涉即可自动转换,而复杂类型,尤其是自定义类型,SWIG提供了typemap供转换。而一旦使用了typemap,配置文件将不再在各个语言当中通用。参考资料:SWIG的官方文档,质量比较高。SWIGUsersManual有个对应的中文版官网,很多年没有更新了。写在最后:由于CPython自身的结构设计合理,使得Python的C/C++扩展非常容易。如果打算快速完成任务,Cython(C/C++调用Python)和SWIG(Python调用C/C++)是很不错的选择。但是,一旦涉及到比较复杂的转换任务,无论是继续使用Cython还是SWIG,仍然需要学习Python源代码。本文使用的开发环境:Python2.7.10Cython0.22SWIG3.0.6Windows10x64RTMCentOS7.1AMD64MacOSX10.10.4文中所述原理与具体环境适用性强。文章所述代码均用于演示,缺乏必备的异常检查
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询