Chinaunix首页 | 论坛 | 博客
  • 博客访问: 163163
  • 博文数量: 65
  • 博客积分: 1790
  • 博客等级: 上尉
  • 技术积分: 460
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-21 23:51
文章分类
文章存档

2012年(8)

2011年(38)

2010年(19)

分类: Python/Ruby

2011-02-24 23:58:16

1. 直接C扩展Python的方法
     Python的扩展API是主要为C语言提供的,可以利用该API为要导出的C函数建立包装器
(wrapper)。包装器用来处理Python对象与底层C函数中的变量与所需值之间的转换,并将C函数注册到Python的自定义module中。
     假设将要导出的函数成为模块函数,对应wrapper中的函数为包装函数。则wrapper文
件主要包含以下几个部分:
Ø        include "Python.h";
Ø        每个模块函数的包装函数,即:PyObject* Module_func();
Ø        每个模块函数的函数定义,即:PyMethodDef ModuleMethods[]对应表;
Ø        模块的初始化函数:void initModule()部分。
     简单示例程序:
     假设有以下C文件example.c:
--------------------------------------------------------------------------------
  /**************** example.c ******************/
double My_variable = 3.0;
int fact(int n)
{
        if (n <= 1)    
               return 1;
        else
               return n*fact(n-1);
}

int my_mod(int n, int m)
{
        return (n % m);
}


--------------------------------------------------------------------------------
 


     我们要导出其中的两个函数fact()和my_mod(),则要为之写wrapper。文件内容如下:
--------------------------------------------------------------------------------
/************* example_wrap.c ***************/
#include

extern int fact(int);
extern int my_mod(int, int);

PyObject *fact_wrap(PyObject *self, PyObject *args)
{
        int num;
        if (!PyArg_ParseTuple(args, "i", &num))
                return NULL;
        return Py_BuildValue("i", fact(num));
}

PyObject *my_mod_wrap(PyObject *self, PyObject *args)
{
        int n, m;

        if (!PyArg_ParseTuple(args, "ii", &n, &m))
                return NULL;
        return Py_BuildValue("i", my_mod(n, m));
}

static PyMethodDef example2methods[] = {
{"fact", fact_wrap, METH_VARARGS, "compute fact of a number"},
{"my_mod", my_mod_wrap, METH_VARARGS, "compute the mod of two numbers"},
{NULL, NULL},
};

void initexample2(void)
{
        Py_InitModule("example2", example2methods);
}
--------------------------------------------------------------------------------
 

     编译连接使用以下命令:
--------------------------------------------------------------------------------
[piaoah@RUDDY example]$ gcc -fpic -c -I/usr/include/python2.2 -

I/usr/lib/python2.2/config example.c example_wrap2.c
[piaoah@RUDDY example]$ gcc -shared -o example2.so example.o example_wrap2.o
[piaoah@RUDDY example]$
--------------------------------------------------------------------------------
 

     则生成共享库文件example2.so。我们可以在Python环境中导入example2模块,并使用其中的函数:
--------------------------------------------------------------------------------
[piaoah@RUDDY example]$ python
Python 2.3.2 (#5, Mar 24 2004, 10:17:17)
[GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-5)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import example2
>>> example2.fact(5)
120
>>> example2.fact(1)
1
>>> example2.fact(3)
6
>>> example2.fact(6)
720
>>> example2.my_mod(1,3)
1
>>>
--------------------------------------------------------------------------------

  
2. 怎样用SWIG生成C的wraper
     SWIG是一个自动的扩展构造工具。它读入注释的源程序头文件(后缀为.i的脚本文件)
,为python、tcl、perl等多种脚本语言产生wrap代码。
     步骤大致为:
(1) 写源程序;
(2) 写后缀为.i的脚本文件;
(3) 使用命令"swig -python example.i"生成example_wrap.c,example_wrap.doc;
(4) 编译连接成共享库。


     .i脚本文件的格式很简单,只需要列出要导出的函数或类型,并注释必要信息。还以
上面的example.c为例,写example.i脚本文件如下:
--------------------------------------------------------------------------------
/**************** example.i ******************/
%module example
%{
#include "example.h"
%}
extern double My_variable;
extern int fact(int);
extern int my_mod(int n, int m);
--------------------------------------------------------------------------------
 
     在命令行输入以下命令"swig -python example.i",会在当前目录下生成
example_wrap.c,example_wrap.doc两个文件。前者即为example.c的wrap文件,后者为解释文件。
     接下来使用编译连接命令生成example.so文件。命令同第一节:
--------------------------------------------------------------------------------
[piaoah@RUDDY example]$ gcc -fpic -c -I/usr/include/python2.2
-I/usr/lib/python2.2/config example.c example_wrap2.c
[piaoah@RUDDY example]$ gcc -shared -o example2.so example.o example_wrap2.o
[piaoah@RUDDY example]$
--------------------------------------------------------------------------------

     接下来就可以在Python环境中使用example模块中的函数了。


3. 用SWIG生成C++的wraper
     用SWIG生成C++的wrapper过程类似于C wrapper。它的步骤如下:
(1) 写.cpp源程序;
(2) 写.i脚本文件;
(3) swig -c++ -python foo.i
生成foo_wrap.c,foo_wrap.doc;
(4) 编译连接成共享库foo.so。
则生成Python的foo模块,可以通过调入foo模块使用其中的类成员函数、成员变量。
     一个简单示例:
     假设有如下C++源程序:
--------------------------------------------------------------------------------
/**************** number.h ******************/
class Number
{
public:
        Number(int start);
        ~Number();
        void add(int value);
        void sub(int value);
        void display();
        int data;
};
--------------------------------------------------------------------------------
 

     对应实现的cpp文件如下:
--------------------------------------------------------------------------------
/***************** number.cpp ****************/
#include "number.h"
#include

Number::Number(int start)
{
    data = start;
    printf("Number: %d\n", data);
}

Number::~Number()
{
    printf("~Number: %d\n", data);
}

void Number::add(int value)
{
    data += value;
    printf("add %d\n", value);
}

void Number::sub(int value)
{
    data -= value;
    printf("sub %d\n", value);
}

void Number::display()
{
    printf("Number = %d\n", data);
}
--------------------------------------------------------------------------------
 

     为之写number.i文件:
--------------------------------------------------------------------------------
%module Number
%{
#include "number.h"
%}

class Number {
public:
        Number(int start);
        ~Number();
        void add(int value);
        void sub(int value);
        void display();
        int data;
};
--------------------------------------------------------------------------------


     使用命令:"swig -c++ -python number.i",得到number_wrap.c,number_wrap.doc
(有些系统生成的是number.py)两个文件。
     再使用命令:
--------------------------------------------------------------------------------
[piaoah@RUDDY example]$ g++ -fpic -c -I/usr/include/python2.2 -

I/usr/lib/python2.2/config number.cpp number_wrap.c
[piaoah@RUDDY example]$ g++ -shared -o number.so number.o number_wrap.o
[piaoah@RUDDY example]$
--------------------------------------------------------------------------------

     生成number.so文件,可以在Python环境中使用Number类及其成员函数。但类名和成员函数名稍有变化,具体可见生成的number_wrap.doc(或number.py)文件。
     接下来便可以在python环境中导入number模块了:
--------------------------------------------------------------------------------
[piaoah@RUDDY NUMBER]$ python
Python 2.3.2 (#5, Mar 24 2004, 10:17:17)
[GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-5)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import number
>>> mynum = Number.new_Number(5)
Number: 5
>>> Number.Number_display(mynum)
Number = 5
>>> Number.Number_add(mynum, 1)
add 1
>>> Number.Number_display(mynum)
Number = 6
>>> Number.Number_sub(mynum, 3)
sub 3
>>> Number.Number_display(mynum)
Number = 3
>>> Number.delete_Number(mynum)
~Number: 3
>>>
--------------------------------------------------------------------------------
 

注:这里使用的SWIG版本为:swig-1.3.24。

转自:http://blog.csdn.net/panbinfeng/archive/2006/04/14/662563.aspx
阅读(1144) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~