swig-python使用和测试

1. SWIG介绍

SWIG 是一个非常优秀的开源工具,支持您将 C/C++ 代码与任何主流脚本语言相集成。

SWIG (Simplified Wrapper and Interface Generator) is anopen source software tool used to connectcomputer programs or libraries written in C or C++ with scripting languages such as Lua, Perl, PHP, Python, R,Ruby, Tcl, and other languages likeC#, Java, Go, Modula-3,OCaml, Octave, and Scheme. Output can also be in the form of XML or Lisp S-expressions.(来自于wiki)

2.SWIG的安装

2.1 下载地址: http://www.swig.org/download.html

2.2 将下载的文件如swig-2.0.8.tar.gz解压

2.3 进入swig-2.0.8目录,执行一下命令 

./configure --prefix=/usr/program/swig/ #或者其他安装目录  
make  
make install  

在./configure 时遇到Cannot find pcre-config script from PCRE (Perl Compatible Regular Expressions)的错误,使用

./configure --prefix=/usr/progam/swig --without-pcre, 因为我使用swig的目的是python

3.SWIG的使用

SWIG支持多种语言(脚本),这里介绍python的一个例子,这个例子是使用c语言模拟位数组,然后交由python扩展

最后有一个使用c扩展python和直接使用python的效率比较

1. 编写c文件

//Bit.h  
#ifndef BIT_H  
#define BIT_H  
  
//create: 2012-10-19  
//version: 1.0  
#define CHAR_LENGTH sizeof(unsigned char)   
  
//Bit模拟位操作  
typedef struct  
{  
    unsigned char *pArray;//指向一个字符型数组,用以存储bit位  
    unsigned long length;//记录pArray的长度, 字符个数  
    unsigned long used;//记录用户使用的bit位  
}Bit;  
  
//创建Bit对象  
//@len: 初始化bit位数  
//@return: 返回一个指向Bit对象的指针, 该指针需要使用freeBit销毁  
Bit* createBit(unsigned long len);  
  
//设置bit位  
//@pb:指向Bit的一个对象, 如果为NULL, 返回1  
//@index: 需要设置的bit位, 范围应当是 (0~used)  
//@value: bit位的值, (0,1)  
//@return: 成功返回0, 如果出现pb==NULL, index out of range, value!=0 and value!=1, 返回1  
int setBit(Bit *pb,unsigned long index, int value);  
  
//获取bit位  
//@pb:指向Bit的一个对象, 如果为NULL, 返回1  
//@index: 需要设置的bit位, 范围应当是 (0~used)  
//@return: 成功返回0, 如果出现pb==NULL, index out of range, 返回1  
int getBit(Bit *pb,unsigned long index);  
  
//返回使用的长度  
//@pb: 如果pb==NULL, return -1  
int bitLength(Bit *pb);  
  
//销毁Bit对象  
void freeBit(Bit *pb);  
#endif  

 
//Bit.c  
#include "Bit.h"  
#include <stdio.h>  
#include <stdlib.h>  
#include <limits.h>  
  
//创建Bit对象  
//@len: 初始化bit位数, len>=0  
//@return: 返回一个指向Bit对象的指针, 该指针需要使用freeBit销毁  
Bit* createBit(unsigned long len)  
{  
    if(len<0)  
        return NULL;  
  
    Bit *pb=(Bit*)malloc(sizeof(Bit));  
    if(len>0)  
    {  
        pb->length=(len-1)/CHAR_LENGTH+1;  
        pb->pArray=(char*)malloc(sizeof(char)*pb->length);  
        pb->used=len;  
    }else  
    {  
        pb->length=0;  
        pb->pArray=NULL;  
        pb->used=len;  
    }  
    return pb;  
}  
  
//设置bit位  
//@pb:指向Bit的一个对象, 如果为NULL, 返回1  
//@index: 需要设置的bit位, 范围应当是 [0~used)  
//@value: bit位的值, (0,1)  
//@return: 成功返回0, 如果出现pb==NULL, index out of range, value!=0 and value!=1, 返回1  
int setBit(Bit *pb,unsigned long index, int value)  
{  
    if(pb==NULL || pb->pArray==NULL || index<0 || index>=pb->used || (value!=0 && value!=1))  
        return 1;  
  
    unsigned long a=index/CHAR_LENGTH;  
    unsigned long b=index%CHAR_LENGTH;  
    if(value==0)  
    {  
        pb->pArray[a]&=(UCHAR_MAX^(1<<b));  
        //printf("%d\n",pb->pArray[a]);  
    }else  
    {  
        pb->pArray[a]|=(1<<b);  
        //printf("%d\n",pb->pArray[a]);  
    }  
    return 0;  
}  
  
//获取bit位  
//@pb:指向Bit的一个对象, 如果为NULL, 返回1  
//@index: 需要设置的bit位, 范围应当是 [0~used)  
//@return: 成功返回0, 如果出现pb==NULL, index out of range, 返回1  
int getBit(Bit *pb,unsigned long index)  
{  
    if(pb==NULL || pb->pArray==NULL || index<0 || index>=pb->used)  
        return 1;  
    unsigned long a=index/CHAR_LENGTH;  
    unsigned long b=index%CHAR_LENGTH;  
    //printf("%d\n",pb->pArray[a]&(1<<b));  
    if((pb->pArray[a]&(1<<b))==0)  
        return 0;  
    else  
        return 1;  
}  
  
//返回使用的长度  
//@pb: 如果pb==NULL, return -1  
int bitLength(Bit *pb)  
{  
    if(pb==NULL || pb->pArray==NULL)  
        return -1;  
    return pb->used;  
}  
  
//销毁Bit对象  
void freeBit(Bit *pb)  
{  
    if(pb==NULL)  
        return;  
    if(pb->pArray!=NULL)  
    {  
        free(pb->pArray);  
        pb->pArray=NULL;  
    }  
    free(pb);  
}  

2. 编写SWIG使用的swg文件

//Bit.i 

%module Bit #module name  
%{  
#include "Bit.h" #加入Bit_wrap.c文件  
%}  
  
#需要导出到python的函数  
extern Bit* createBit(unsigned long len);  
extern int setBit(Bit *pb,unsigned long index, int value);  
extern int getBit(Bit *pb,unsigned long index);  
extern int bitLength(Bit *pb);  
extern void freeBit(Bit *pb);  


3. 编译

3.1 使用swg文件生成wrap文件

使用Bit.i生成wrap文件

该命令得到Bit_wrap.c Bit.py (Bit_wrap.c是python调用c的接口封装 ,Bit.py 是向python提供接口并使用python的c库调用动态库

[username]$ swig -python Bit.i  

3.2 编译源文件得到目标文件

编译Bit.c Bit_wrap.c文件(Bit.c 是实现逻辑的文件, Bit_wrap.c是python调用c的接口封装 )

[username]$ gcc -c -fpic Bit.c Bit_wrap.c -I${PYTHON_INCLUDE}  

-fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),
则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意
位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

PYTHON_INCLUDE为python安装目录下的include文件夹, 如/usr/program/python/include/python.2.7

3.3 连接目标文件得到动态库 

[username]$ gcc -shared Bit.o Bit_wrap.o -o _Bit.so 

注意输出库文件为_Bit.so, 有下划线和模块名称组成

4.使用动态库作为python库

这里以计算一亿一下的素数个数来演示

将Bit.py和_Bit.so文件复制到需要的位置

编写prime_count.py

#coding=utf-8  
#create-2012-10-17  
#version: 1.0  
#计算小于1亿的素数个数  
  
import time  
from Bit  import *  
  
MAX=100000000  
count=1  
  
#0 表示素数  
#1 表示已经去除  
  
start_time=time.time()  
  
len=MAX/2-1  
b=createBit(len)  
  
def remove(idx):  
    i=idx  
    global b  
    while i<len:  
        #b[i]=1  
        setBit(b,i,1)  
        i+=2*idx+3  
  
for i in range(3,MAX,2):  
    if getBit(b,(i-3)/2)==0:  
        #素数  
        count+=1  
        remove((i-3)/2)  
  
end_time=time.time()  
print count  
print end_time-start_time  

使用方法和其他python提供的模块一样

5.附计算结果

使用以上方法(c扩展python)得到结果为: 

5761455(素数个数)  
113.465720892(second)  

另外,如果直接使用python模拟bit,并同样计算一亿一下的素数个数,结果为 

5761455(素数个数)  
293.473055124(second)  

可以看到,性能提升非常明显(接近3倍),当然这只是一个例子,并不具有太多代表性

另附,同样的方法,如果是c语言,调用我们实现的Bit的话结果为: 

5761455(素数个数)  
5(second)  


计算这种事情还是交给c做比较恰当


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值