使用SIP对C++类进行Python封装

Python中使用C/C++模块有许多工具,大名鼎鼎的有SWIG(英文意思为:豪饮)、SIP(英文意思为:啜饮,小口的喝),还有 boost.python等。其中SIP是从SWIG发展而来,专为Python调用C/C++模块使用的(看SIP的命名就能看出来,很有意思的)。

SIP的使用方法,在官网的SIP Reference Guide中有介绍,不过那是针对至少有点经验的人员,对初学者来说,想十分钟快速上手还是有点难度的。这里就介绍下本人在使用SIP总结的需要注意的地 方。(本着方便大家方便自己的原则,欢迎转载,无需征得本人同意,但请注明出处,最好是原文连接,图个人气,谢谢!)

前提,本机上要装了Python、GCC(Windows下可以用MinGW,在我的Eclipse下配置CDT一文中有关于MinGW的安装介绍)。并把python.exe和MinGW下的bin文件路径添加到环境变量中。

第一部分:安装SIP

Windows:

将Riverbank上的sip的zip格式的代码包下载,将其解压到C:\Python27中,那么现在sip的文件夹路径为C: \Python27\sip-4.13.2\sip-4.13.2(你也可以将其解压到任何一个文件夹中,但这里为了叙述方便,就解压到我电脑上的 Python的文件夹中)。

打开Windows的cmd命令行,输如cd C:\Python27\sip-4.13.2\sip-4.13.2跳转到sip文件夹下。

输入python configure.py --platform win32-g++。进行配置,显示结果如下:

再完成上一步后,输入mingw32-make,接着输入mingw32-make install。若无意外,SIP就安装完成了。

常见问题:

若是你的电脑上之前安装了Eclipse等其他软件,而将mingw32-make改成了make,那么就要将上面的mingw32-make命令改为make来使用。

有个朋友说他按上面的方法使用make总是报错,仔细一问,才发现他的电脑上安装了Embacardero的RAD开发工具,也就是熟知的 Delphi和C++ Builder的开发工具。在安装了这个工具后,在命令行中输入make,使用的总是Embacardero的 C++ Builder的make。根据亲测,即使在配置的时候,使用python configure.py --platform win32-borland命令进行配置,对Emcarbadero的make也是无效的。这个配置命令产生的make文件,只是用于老版本的 Borland C++ Builder的make命令。

若要使用微软的VC的nmake,就要在配置时使用命令python configure.py --platform win32-msvc,其中win32-msvc使用的是VC6的nmake;win32-msvc.net使用的是VC2003的 nmake;win32-msvc2005使用的是VC2005的nmake;win32-msvc2008使用的是VC2008的nmake。根据 --show-platforms命令显示的结果,SIP的配置暂不支持VC2010和VS11下的nmake。若想知道SIP支持的所有平台和编译器, 可以在命令行中使用python configure.py --show -platforms命令来查看。

Linux:

Linux下的SIP安装与之类似,甚至更简单,Linux的发行版如Ubuntu,都自动安装了python和gcc,无需配置环境变量。

所以只要在官网上下载SIP的Linux下的tar.gz格式的代码包,解压到某个目录中。然后在终端中进入该目录,依次输入python configure.py --platform linux-g++;make;make install即可。

在Python中使用C/C++写的函数。

1、首先,编写个C文件,功能是将两个数字相加并输出,命名为add.c,这个将成为在Python中的模块名,如下:

/* File : add.c */  
int add(int x, int y)   
{    
    int g;    
    g = x + y;  
    return g;  
}

2、接着,手工编写SIP文件,在使用SIP的过程中,一个C/C++的源码文件,必须对应一个同名的sip文件,命名为add.sip,如下:

[plain] view plaincopy

  1. /* Define the SIP wrapper to the add library. */
  2. %Module(name=add, language="C")
  3. int add(int x, int y);

如果是源程序是用C++写的,那么这里的(name=add, language="C")就可以省去。
        这里的C源码文件没有头文件,所以对应的sip文件很简单。如果C/C++的源码是实现部分,在实现部分还包括接口部分,即头文件。那么在相应的sip文件中需要用

[cpp] view plaincopy

  1. %TypeHeaderCode
  2. #include <word.h>
  3. %End

来包含相应的头文件。sip文件与正式的C/C++头文件相似,但与之不同的是:sip文件不包含相应的头文件的私有成员变量(private或 protected)。更详细的sip文件编写规范,请参考riverbank官方网站上的说明文档SIP Reference Guide。

3、编译C文件。按照官网的说法,是编写configure.py,但别急,先做一些必不可少的工作。在命令行将add.c编译成add.o文件:输入

[sql] view plaincopy

  1. gcc -c add.c

接着,将这一步生成的add.o文件生产库文件:

[plain] view plaincopy

  1. ar -r libadd.a add.o

这两步在这里是为一个单独的C模块测试的,如果是大量的C模块,可以用一个makefile一并批量完成,这也是初学者容易模糊的地方。记住,需要将libadd.a文件复制到Python文件夹下的libs文件夹中。也可以将源代码直接编译成dll,命令为

4、手工编写configure.py文件,同样,这个configure文件的编写也不难,看下规范就会了(要会鸟语。。。)。这里,我们模仿官网的模版写一个自己的configure.py。

[python] view plaincopy

  1. import os
  2. import sipconfig
  3. # The name of the SIP build file generated by SIP and used by the build
  4. # system.
  5. build_file = "add.sbf"
  6. # Get the SIP configuration information.
  7. config = sipconfig.Configuration()
  8. # Run SIP to generate the code.
  9. os.system(" ".join([config.sip_bin, "-c", ".", "-b", build_file, "add.sip"]))
  10. # Create the Makefile.
  11. makefile = sipconfig.SIPModuleMakefile(config, build_file)
  12. # Add the library we are wrapping.  The name doesn‘t include any platform
  13. # specific prefixes or extensions (e.g. the "lib" prefix on UNIX, or the
  14. # ".dll" extension on Windows).
  15. makefile.extra_libs = ["add"]
  16. # Generate the Makefile itself.
  17. makefile.generate()

5、运行configure.py,会生成一个makefile文件(直接用IDLE打开configure.py,按F5运行;或者命令行用python configure.py运行都可以)。
这里有个诡异的地方,有几个朋友在这一步会报错,说找不到add.sbf文件,而add.sbf文件应该是configure.py运行时调用相关函数自 动产生的。若出现这个问题,请重新编译SIP。如果是Windows下,最好是在另一台机器上拷贝一个完整的包含能正常的SIP的Python文件夹,到 有问题的机器上,将问题Python文件夹覆盖掉。

6、在命令行输入make(这里会生成一个关于函数的警告,不用管它,我们是用来测试的。。。其他的应该没什么问题,若有问题请检查前面的步骤),生成add.pyd文件。然后再输入make install(将add.pyd文件装入到Python的Lib文件夹下的sit-packages文件夹中)。

7、打开Python 的命令行,进行测试:

[python] view plaincopy

  1. >>>import add
  2. >>>add.add(4, 7)
  3. 11
  4. >>>

(原谅我这么烂的模块名。。。)

提示:

(1)、这些文件可以放到Python的文件夹下新建的文件夹中(所有的操作在这个目录下的命令行窗口中使用)。注意,Python的父文件夹名不能有空格,否则会无法读取库文件。

(2)、使用MinGW,需要把~\MinGW\bin添加的环境变量中(Linux下则不必),这样才能使用gcc、make和ar等工具。

时间: 2024-10-30 21:25:32

使用SIP对C++类进行Python封装的相关文章

python 封装底层实现原理

事实上,python封装特性的实现纯属"投机取巧",之所以类对象无法直接调用私有方法和属性,是因为底层实现时,python偷偷改变了它们的名称. python在底层实现时,将它们的名称都偷偷改成了"_类名__属性(方法)名"的格式 class Person: def setname(self, name): if len(name) < 3: raise ValueError('名称长度必须大于3!') self.__name = name def getna

ffmpeg学习4--ffmpeg类的简单封装,包含解码和定时录像功能

ffmpeg学习4--ffmpeg类的简单封装,包含解码和定时录像功能 参考网上的资料,简单封装了一下ffmpeg,这里记录一下,其它传感器编码及项目中用到的已经抽离,这里只包含解码和录像部分.这只是个玩具级别的测试.完整测试代码下载:代码下载 ffmpegDeCode.h #pragma once #include "stdafx.h" #include<iostream> using namespace std; extern char *VideoPath; exte

分析特定类的python脚本

今天接触了下pyUSB,事先没看对象内部成员资料,直接用python的dir函数看了看pyUSB的内部构成.突然间想到自己可不可以写个简单的脚本,利用dir或其他函数遍历某个对象内部的所有成员,并打印出来成树状图的形式?于是写了如下对象分析程序: 使用方法 : import matplotlib.pyplot as plt import AnalysisClass m = AnalysisClass.AnalysisClass() m.analysisObject(plt.Arrow, 'plt

并查集类的c++封装,比较union_find algorithm四种实现方法之间的性能差别

问题描述: 在计算机科学中,并查集是一种树型的数据结构,其保持着用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.有一个联合-查找算法(union-find algorithm)定义了两个操作用于此数据结构: Find:确定元素属于哪一个子集.它可以被用来确定两个元素是否属于同一子集: Union:将两个子集合并成同一个集合: 实现并查集的关键是实现union-find algorithm, 本文根据常用的四种算法,实现了这个类,具体算法实现请参看维基百科: 制造测试数据集,

Python封装应用程序的最佳项目结构是什么?

Python封装应用程序的最佳项目结构是什么? 转载来源于stackoverflow:https://stackoverflow.com/questions/193161/what-is-the-best-project-structure-for-a-python-application 和http://www.cnblogs.com/alex3714/articles/5765046.html#3719169 开发一个终端用户桌面应用(非网页),最佳的项目文件夹层次结构是怎样的? 理想的项目

一个依靠STL vector的接口进行申请和回收管理的内存池类( c++ 封装)

其他出现两次,只有一个出现一次的那道题我就不更了,直接抑或,最后的结果就是那个数.为什么可以这样做呢?因为一个32位int,如果所有数都出现了两次,那么为1的那些位统计的个数一定是2的倍数,抑或之后全变成0.一个数出现了一次,它为1的那些位上,1的个数必定是奇数,抑或之后一定还是1. 我之前知道出现两次这个题的解法,但是理解的不够深,以为抑或是关键,其实不是,出现了偶数次才是关键.理解了这点,推广到出现3次上,如果所有的出现了三次,那么为1的那些位1的个数一定是三的倍数,那如果有一个数出现了一次

【C++】多个类的DLL封装及调用

[C++]多个类的DLL封装及调用 分类: [编程语言]2012-07-11 18:53 6399人阅读 评论(12) 收藏 举报 dllc++includebuild2010 目录(?)[+] 网上大多是将函数封装成dll的教程,类的封装也是基本相似的. 创建DLL 在VS2010中新建一个win32->dll工程.如我建立的工程名为FaceDLL 添加facedll.h的头文件(里面定义dll的接口,调用时会用到) [cpp] view plaincopy #pragma once #ifd

使用uiautomator的python封装进行android的UI测试

最近项目中有个需求要在至少100台手机上对应用进行兼容性测试,首先想到的就是自动化来操作,不想一台台的操作相同的重复操作 基本的需求是这样的,安装被测试的应用,启动并退出,然后安装测试样本,检测是否有相应的弹窗拦截 考虑到市面上的各种测试框架与自已熟悉的编程语言,最后选择了google自家的uiautomator来搞,借助于前人对其进行了python封装,所以一开始还是挺顺利的,但是整个过程中还是有很多需要注意的地方 https://github.com/xiaocong/uiautomator

把jQuery的类、插件封装成seajs的模块的方法

这篇文章主要介绍了把jQuery的类.插件封装成seajs的模块的方法,需要的朋友可以参考下 注:本文使用的seajs版本是2.1.1 一.把Jquery封装成seajs的模块 define(function () { //这里放置jquery代码 把你喜欢的jquery版本放进来就好了 return $.noConflict(); }); 调用方法: 这样引进就可以像以前一样使用jquery define(function (require, exports, module) { var $