swig-python-之初

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);
}

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 使用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, 有下划线和模块名称组成
4.使用,这里以计算一亿一下的素数个数来演示

将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做比较恰当

关于更多素数计算的信息见我的博客-数的计算


你的反馈就是博主进步的最大动力

你可能感兴趣的:(c,c++,python)