1. SWIG介绍(来自于wiki)
SWIG (Simplified Wrapper and Interface Generator) is anopen source software tool used to connect computer 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.
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
#include
#include
//创建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<pArray[a]);
}else
{
pb->pArray[a]|=(1<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<pArray[a]&(1<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);
}
//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.1 使用Bit.i生成wrap文件,该命令得到Bit_wrap.c Bit.py
[username]$ swig -python Bit.i
3.2 编译Bit.c Bit_wrap.c文件,其中PYTHON_INCLUDE为python安装目录下的include文件夹, 如/usr/program/python/include/python.2.7username]$ gcc -c
[username]$ gcc -c -fpic Bit.c Bit_wrap.c -I${PYTHON_INCLUDE}
3.3 连接得到动态库
[username]$ gcc -shared Bit.o Bit_wrap.o -o _Bit.so
注意输出库文件为_Bit.so, 有下划线和模块名称组成
将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
使用方法和其他python提供的模块一样
5.附计算结果
使用以上方法(c扩展python)得到结果为:
5761455(素数个数)
113.465720892(second)
另外,如果直接使用python模拟bit,并同样计算一亿一下的素数个数,结果为
5761455(素数个数)
293.473055124(second)
可以看到,性能提升非常明显(接近3倍),当然这只是一个例子,并不具有太多代表性
另附,同样的方法,如果是c语言,调用我们实现的Bit的话结果为:
5761455(素数个数)
5(second)
计算这种事情还是交给c做比较恰当
关于更多素数计算的信息见我的博客-数的计算
你的反馈就是博主进步的最大动力