swig 把c/c++ 封装成python可调用的so文动态链接库

时间:2021-05-17 21:56:39

注意:使用此种方法产生的so文件放在 python的site 目录下,可以直接import example,调用模块。

我们经常会看到python一些项目源码中,有的方法直接pass

 def has_key(self, k): # real signature unknown; restored from __doc__
""" D.has_key(k) -> True if D has a key k, else False """
return False

def items(self): # real signature unknown; restored from __doc__
""" D.items() -> list of D's (key, value) pairs, as 2-tuples """
return []

def iteritems(self): # real signature unknown; restored from __doc__
""" D.iteritems() -> an iterator over the (key, value) items of D """
pass


但是,他们确实执行了,什么原因呢,就是使用了swig制作的so文件。


C 和 C++ 被公认为(理当如此)创建高性能代码的首选平台。对开发人员的一个常见要求是向脚本语言接口公开 C/C++ 代码,这正是 Simplified Wrapper and Interface Generator (SWIG) 的用武之地。SWIG 允许您向广泛的脚本语言公开 C/C++ 代码,包括 Ruby、Perl、Tcl 和 Python等。

为了建立python的扩展模块,SWIG采用分层的策略:用c写扩充模块,其余部分用python写。c包含低层次的封装,而python包含高层次的封装。分层策略是扩展模块的特定部分用特定的语言完成(而不全部用c/c++完成),另外通过利用2种语言,可以发挥各自语言的特性,增加灵活性。

 注意这个动态链接库可直接调用,而不用

1. 安装SWIG(ubuntu)

1. 下载 swig 源码


http://www.swig.org/survey.html

填写一个简单的问卷,即可进入 sourceforge 下载。


2. 安装 g++


sudo apt-get install g++


如果安装过,无需再次安装。步骤 3 同理。

检验一下你的系统是否安装了 g++,输入

g++ -version



3. 安装 pcre


sudo apt-get install libpcre3 libpcre3-dev



4. 解压 swig 源码 


chmod 777 swig-2.0.11.tar.gz // 改变权限
tar -xzvf swig-2.0.11.tar.gz // 解压



5. 配置、编译和安装 swig


cd 到刚才解压的目录里面

./configure --prefix=/usr/local/share/swig3.0.12 // 指定安装目录
make // 编译
make install // 安装


如果想让默认安装的话,可以直接执行./configure


6. 配置 path


sudo vim /etc/profile


把swig的安装bin路径添加到环境变量中

PATH=/usr/local/share/swig3.0.12/bin:$PATH


这样,在其他路径下就可以执行 swig 命令。


7.查看版本信息


swig 把c/c++ 封装成python可调用的so文动态链接库


安装成功!

 

2. 例子(c语言)

附上整好的目录,本人做的时候

.
├── build
│   ├── lib.linux-x86_64-2.7
│   │   └── _example.so
│   └── temp.linux-x86_64-2.7
│       ├── example.o
│       └── example_wrap.o
├── example.c
├── example.h
├── example.i
├── example.py
├── example.pyc
├── _example.so
├── example_wrap.c
└── setup.py


2. 例子(c语言)

#2.1 用c语言编写头文件和源文件为

/* File: example.h */

int fact(int n);

 

/* File: example.c */

#include
"example.h"

int fact(int n) {
if (n < 0){ /* This should probably return an error, but this is simpler */
return 0;
}
if (n == 0) {
return 1;
}
else {
/* testing for overflow would be a good idea here */
return n * fact(n-1);
}
}

 

#2.2 写swig模块写一个文件

/* File: example.i */
%module example

%{
#define SWIG_FILE_WITH_INIT
#include
"example.h"
%}

int fact(int n);

 

#2.3 为了建python模块,利用-python参数执行swig

1 swig
-python example.i

执行完命令后生成两个不同的文件:example_wrap.c和example.py。

自动生成文件名的原则:生成的c文件名与写的c文件名有关(例如写的c文件名为example.c则生成example_wrap.c);生成的python文件即.i文件中%module后面的名字。

 

#2.4 利用distutils生成动态库

python自带一个distutils工具,可以用它来创建python的扩展模块。使用它也很简单,只需要先定义一个配置文件,通常是命名为setup.py

123456789101112131415161718 """setup.py""" from
distutils.core import setup, Extension
  example_module
= Extension(
'_example',
                           sources=['example_wrap.c''example.c'],                           ) setup
(name = 
'example',
       version = '0.1',       author      = "SWIG Docs",       description = """Simple swig example from docs""",       ext_modules = [example_module],       py_modules = ["example"],       )

:头文件和源文件都是example.*,那么setup.py脚本中Extension的参数必须为“_example”

 

#2.5 编译

1 python
setup.py build

会在本目录下build/lib*/下生成_example.pyd模块,可以直接使用,例如

1234 >>>import
example
>>>print example.fact(4)24>>>

可以以使用下面命令生成so动态库,下面命令会生成example.so

1 python
setup.py build_ext --inplace

把example.so 放在 python的site 目录下,如/usr/local/lib/python2.7/dist-packages目录下,import example会自动加载

import example
print example.fact(4)


3. 例子(c++)

和c一样,稍微区别

#3.1 用c语言编写头文件和源文件为

/* File: example.h */

int fact(int n);

 

/* File: example.cpp */

#include "example.h"

int fact(int n) {
if (n < 0){ /* This should probably return an error, but this is simpler */
return 0;
}
if (n == 0) {
return 1;
}
else {
/* testing for overflow would be a good idea here */
return n * fact(n-1);
}
}

 

#3.2 给swig模块写一个文件

/* File: example.i */
%module example

%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}

int fact(int n);

 

#3.3 为了建python模块,利用-python参数执行swig

1 swig
-c++ -python example.i

执行完命令后生成两个不同的文件:example_wrap.cxx和example.py。

 

#3.4 利用distutils生成动态库

python自带一个distutils工具,可以用它来创建python的扩展模块。使用它也很简单,只需要先定义一个配置文件,通常是命名为setup.py

123456789101112131415161718 """setup.py""" from
distutils.core import setup, Extension
  example_module
= Extension(
'_example',
                           sources=['example_wrap.cxx''example.cpp'],                           ) setup
(name = 
'example',
       version = '0.1',       author      = "SWIG Docs",       description = """Simple swig example from docs""",       ext_modules = [example_module],       py_modules = ["example"],       )

:头文件和源文件都是example.*,那么setup.py脚本中Extension的参数必须为“_example”

 

#3.5 编译,会生成example.so,

1 python
setup.py build_ext --inplace

把example.so 放在 python的site 目录下,如/usr/local/lib/python2.7/dist-packages目录下,import example会自动加载

import example
print example.fact(4)


如果使用 pycharm等IDE工具查看源码,您会看到如下
# encoding: utf-8
# module _example
# from /usr/local/lib/python2.7/dist-packages/_example.so
# by generator 1.138
# no doc
# no imports

# functions

def fact(*args, **kwargs): # real signature unknown
pass

def SWIG_PyInstanceMethod_New(*args, **kwargs): # real signature unknown
pass

# no classes