SWIG 学习
札记    无    2014-07-31 11:03:05    534    0    0

Python 确实是一门不错的编程语言,以其构建速度快而广受懒惰的程序员们的喜爱.但是 Python 也有一个难言之隐—-运行速度太慢了,Pypy 项目不知所云, JIT 遥遥无期. 高级语言在遇到性能问题的时候总是会想起向 C 求救.Python有专门用来写 C 扩张的 Cython , 但是搅在一起的 C 和 Python 写起来总有些别扭.但是,我们还有 SWIG.

SWIG 是通用的高级语言和 C/C++ 的接口生成器.看了看几乎所有的高级语言都支持了.尝试使用了下,也感觉比较顺利.优雅的 Python 借力 C 的高效,一定让你爱不释手.

示例

大致的流程是 编写C -> 通过SWIG 转为 wrap -> 编译成动态库 -> 动态库可以被 python 当模块一样调用

示例 C 文件如下,包含 .c 和 .h 文件,都是必须的.

#ifndef __TEST_H__
#define __TEST_H__

#define MAX 42
extern int gNum;
extern void hello(void);
extern int gcd(int x, int y);

#endif
```C
#include "test.h"
#include "stdio.h"

// 变量
int gNum = 100;

// 基本函数
void hello(void)
{
    printf("hello world~\r\n");
}

// 带参数的函数
int gcd(int x, int y)
{
    int g = y;

    while (x > 0)
    {
        g = x;
        x = y % x;
        y = g;
    }

    return g;
}
```
/* File .i */
%module test
%{
#include "test.h"
%}

%include "test.h"

在 windows 下操作的, 需要安装好 vs 编译环境,配置好 cl.exe 的路径. Linux 就直接用 gcc

C:\swig\test>swig -python test.i

C:\swig\test>cl /Fe_test.pyd /LD test.c test_wrap.c c:\Python27\libs\python27.li
b /Ic:\Python27\include
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.

test.c
test_wrap.c
Generating Code...
Microsoft (R) Incremental Linker Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

/out:_test.pyd
/dll
/implib:_test.lib
test.obj
test_wrap.obj
c:\Python27\libs\python27.lib
   Creating library _test.lib and object _test.exp

C:\swig\test>python
Python 2.7.6 (default, Nov 10 2013, 19:24:18) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> import _test
>>> dir(_test)
['MAX', 'SWIG_PyInstanceMethod_New', '__doc__', '__file__', '__name__', '__packa
ge__', 'cvar', 'gcd', 'hello']
>>> _test.MAX
42
>>> _test.MAX = 2
>>> _test.MAX
2
>>> _test.hello()
hello world~
>>> _test.gcd(3,9)
3
>>>

Linux 下命令使用编译 .so 文件

gcc -O2 -fPIC -c test.c
gcc -O2 -fPIC -c test_wrap.c -I /usr/include/python2.7/
gcc -shared test.o test_wrap.o -o _test.so

发现,C 里面的宏定义也是会被改变值的.要不被改变还是要自己修饰.手册中还有多种方法能够实现指针的获取和传递,包括函数指针.返回 malloc 的对象也是可以的,但是需要自己手动去释放内存.(我个人不喜欢这样用).以及 C++ 的类的支持.

文档导航