swig
C 和 C++ 被公认为(理当如此)创建高性能代码的首选平台。对开发人员的一个常见要求是向脚本语言接口公开 C/C++ 代码,这正是 Simplified Wrapper and Interface Generator (SWIG) 的用武之地。SWIG 允许您向广泛的脚本语言公开 C/C++ 代码,包括 Ruby、Perl、Tcl 和 Python。
Simplified Wrapper and Interface Generator简化的包装器和接口生成器
SWIG 是一款不错的工具,可适合多种场景,其中包括:
向 C/C++ 代码提供一个脚本接口,使用户更容易使用 向您的 Ruby 代码添加扩展或将现有的模块替换为高性能的替代模块 提供使用脚本环境对代码执行单元和集成测试的能力 使用 TK 开发一个图形用户接口并将它与 C/C++ 后端集成 此外,与 GNU Debugger 每次都需触发相比,SWIG 要容易调试得多。
1、安装swig
linux下载地址:https://sourceforge.net/projects/swig/files/swig/swig-4.0.2/swig-4.0.2.tar.gz/download?use_mirror=udomain windows下载地址:https://sourceforge.net/projects/swig/
使用tar -zxvf swig-4.0.2.tar.gz解压后configure报错,需要安装pcre。
checking whether to enable PCRE support... yes
checking whether to use local PCRE... no
checking for a sed that does not truncate output... /bin/sed
checking for pcre-config... no
configure: error: in `/media/hankin/vdb/swig/swig-4.0.2':
configure: error:
Cannot find pcre-config script from PCRE (Perl Compatible Regular Expressions)
library package. This dependency is needed for configure to complete,
Either:
- Install the PCRE developer package on your system (preferred approach).
- Download the PCRE source tarball, build and install on your system
as you would for any package built from source distribution.
- Use the Tools/pcre-build.sh script to build PCRE just for SWIG to statically
link against. Run 'Tools/pcre-build.sh --help' for instructions.
(quite easy and does not require privileges to install PCRE on your system)
- Use configure --without-pcre to disable regular expressions support in SWIG
(not recommended).
See `config.log' for more details
2、安装pcre2(最终选择放弃,最后选择安装pcre)
下载地址:https://ftp.pcre.org/pub/pcre/
./configure
make
make install
结果安装swig还是报错了,还是报同样的错误。
尝试执行pcre-config命令发现只有pcre2-config,凭直觉认为可能是版本升级了的原因,跟python2和python3一样的道理。
通过执行ln -s /usr/local/bin/pcre2-config /usr/local/bin/pcre-config创建软连接,然后再configure就成功了。
3、安装pcre
不能高兴太早,make的时候报错:
mv -f $depbase.Tpo $depbase.Po
Swig/misc.c:1315:18: fatal error: pcre.h: 没有那个文件或目录
compilation terminated.
Makefile:933: recipe for target 'Swig/misc.o' failed
make[2]: *** [Swig/misc.o] Error 1
make[2]: Leaving directory '/media/hankin/vdb/swig/swig-4.0.2/Source'
Makefile:602: recipe for target 'all' failed
make[1]: *** [all] Error 2
make[1]: Leaving directory '/media/hankin/vdb/swig/swig-4.0.2/Source'
Makefile:37: recipe for target 'source' failed
make: *** [source] Error 2
再次尝试把/usr/local/include/pcre2.h重命名为pcre.h,结果后面还有一系列的pcre2错误,还是老老实实安装pcre吧。
下载安装pcre成功,然后make swig结果还是失败:
g++ -g -O2 -Wall -W -ansi -pedantic -o eswig CParse/cscanner.o CParse/parser.o CParse/templ.o CParse/util.o DOH/base.o DOH/file.o DOH/fio.o DOH/hash.o DOH/list.o DOH/memory.o DOH/string.o DOH/void.o Doxygen/doxyentity.o Doxygen/doxyparser.o Doxygen/doxytranslator.o Doxygen/javadoc.o Doxygen/pydoc.o Modules/allocate.o Modules/browser.o Modules/contract.o Modules/csharp.o Modules/d.o Modules/directors.o Modules/emit.o Modules/go.o Modules/guile.o Modules/interface.o Modules/java.o Modules/javascript.o Modules/lang.o Modules/lua.o Modules/main.o Modules/mzscheme.o Modules/nested.o Modules/ocaml.o Modules/octave.o Modules/overload.o Modules/perl5.o Modules/php.o Modules/python.o Modules/r.o Modules/ruby.o Modules/scilab.o Modules/swigmain.o Modules/tcl8.o Modules/typepass.o Modules/utils.o Modules/xml.o Preprocessor/cpp.o Preprocessor/expr.o Swig/cwrap.o Swig/deprecate.o Swig/error.o Swig/extend.o Swig/fragment.o Swig/getopt.o Swig/include.o Swig/misc.o Swig/naming.o Swig/parms.o Swig/scanner.o Swig/stype.o Swig/symbol.o Swig/tree.o Swig/typemap.o Swig/typeobj.o Swig/typesys.o Swig/wrapfunc.o -ldl
Swig/misc.o:在函数‘Swig_string_regex’中:
/media/hankin/vdb/swig/swig-4.0.2/Source/Swig/misc.c:1480:对‘pcre_free’未定义的引用
/media/hankin/vdb/swig/swig-4.0.2/Source/Swig/misc.c:1461:对‘pcre_compile’未定义的引用
/media/hankin/vdb/swig/swig-4.0.2/Source/Swig/misc.c:1468:对‘pcre_exec’未定义的引用
/media/hankin/vdb/swig/swig-4.0.2/Source/Swig/misc.c:1480:对‘pcre_free’未定义的引用
/media/hankin/vdb/swig/swig-4.0.2/Source/Swig/misc.c:1480:对‘pcre_free’未定义的引用
Swig/misc.o:在函数‘Swig_pcre_version’中:
/media/hankin/vdb/swig/swig-4.0.2/Source/Swig/misc.c:1485:对‘pcre_version’未定义的引用
Swig/naming.o:在函数‘name_regexmatch_value’中:
/media/hankin/vdb/swig/swig-4.0.2/Source/Swig/naming.c:1103:对‘pcre_compile’未定义的引用
/media/hankin/vdb/swig/swig-4.0.2/Source/Swig/naming.c:1111:对‘pcre_exec’未定义的引用
/media/hankin/vdb/swig/swig-4.0.2/Source/Swig/naming.c:1112:对‘pcre_free’未定义的引用
collect2: error: ld returned 1 exit status
Makefile:848: recipe for target 'eswig' failed
make[2]: *** [eswig] Error 1
make[2]: Leaving directory '/media/hankin/vdb/swig/swig-4.0.2/Source'
Makefile:602: recipe for target 'all' failed
make[1]: *** [all] Error 2
make[1]: Leaving directory '/media/hankin/vdb/swig/swig-4.0.2/Source'
Makefile:37: recipe for target 'source' failed
make: *** [source] Error 2
对于我这个老江湖,这个错误铭记在心,很明显是pcre缺少共享库so文件。 重新编译安装pcre试试。 看了一下pcre的配置./configure --help
--disable-dependency-tracking
speeds up one-time build
--enable-shared[=PKGS] build shared libraries [default=yes]
--enable-static[=PKGS] build static libraries [default=yes]
--enable-fast-install[=PKGS]
optimize for fast installation [default=yes]
--disable-libtool-lock avoid locking (might break parallel builds)
默认是开启的,我心态崩了啊。
但是我还是尝试重新编译安装pcre,./configure --enable-shared,然后再重新编译安装swig ./configure,结果安装成功了。 不清楚是重新configure成功,还是--enable-shared成功,我猜测是--enable-shared的原因。
4、编写swig文件
作为输入,SWIG 需要一个包含 ANSI C/C++ 声明和 SWIG 指令的文件。我将此输入文件称为 SWIG 接口文件。一定要记住,SWIG 仅需要足够生成包装器代码的信息。该接口文件通常具有 .i 或 .swg 扩展名。
编写swig文件test_swig.i:
//%module 后面的名字是被封装的模块名称。封装口,python通过这个名称加载程序
//%{ %}之间所添加的内容,一般包含此文件需要的一些函数声明和头文件。
//最后一部分,声明了要封装的函数和变量,直接使用%include 文件模块头文件直接包含即可
%module test_swig
%{
#define SWIG_WITH_INIT
#include "test_swig.hpp"
%}
%include "test_swig.hpp"
5、执行swig文件
[root@ubuntu0006:/media/hankin/vdb/swig/test] #g++ test_swig_main.cpp
test_swig.hpp:1:9: warning: #pragma once in main file
#pragma once
^
/tmp/ccjItqEm.o:在函数‘main’中:
test_swig_main.cpp:(.text+0x38):对‘add(int, int)’未定义的引用
test_swig_main.cpp:(.text+0x58):对‘sub(int, int)’未定义的引用
collect2: error: ld returned 1 exit status
[root@ubuntu0006:/media/hankin/vdb/swig/test] #g++ test_swig_main.cpp test_swig.cpp
[root@ubuntu0006:/media/hankin/vdb/swig/test] #./a.out
x = 10, y = 8
x + y = 18
x - y = 2
[root@ubuntu0006:/media/hankin/vdb/swig/test] #vim test_swig.i
[root@ubuntu0006:/media/hankin/vdb/swig/test] #swig -python -c++ test_swig.i
swig: error while loading shared libraries: libpcre.so.1: cannot open shared object file: No such file or directory
[root@ubuntu0006:/media/hankin/vdb/swig/test] #find /usr/local/lib -name libpcre.so.1
/usr/local/lib/libpcre.so.1
[root@ubuntu0006:/media/hankin/vdb/swig/test] #which swig
/usr/local/bin/swig
[root@ubuntu0006:/media/hankin/vdb/swig/test] #ldd /usr/local/bin/swig
linux-vdso.so.1 => (0x00007ffe37fc9000)
libpcre.so.1 => not found
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fbac4853000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fbac463d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbac4273000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fbac3f6a000)
/lib64/ld-linux-x86-64.so.2 (0x00007fbac4bd5000)
[root@ubuntu0006:/media/hankin/vdb/swig/test] #cp /usr/local/lib/libpcre.so.1 /usr/lib/
[root@ubuntu0006:/media/hankin/vdb/swig/test] #ldd /usr/local/bin/swig
linux-vdso.so.1 => (0x00007ffd465ad000)
libpcre.so.1 => /usr/lib/libpcre.so.1 (0x00007f80ab7e5000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f80ab463000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f80ab24d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f80aae83000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f80aab7a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f80aba03000)
6、编写setup.py文件
参考:https://blog.csdn.net/qq_26105397/article/details/83153606
网站没有给出import头文件,发现Extension和setup在distutils和setuptools中。
distutils和setuptools的联系与区别
distutils仍然是使用python打包的标准工具,它包含在标准库中,它对于简单的python发型版很有用,但缺少功能。 setuptools是为克服Distutils的局限性而开发的,它不包含在标准库中,它引入了一个名为easy_install的命令行实用程序。
建议: 除非你的要求非常基本并且需要distuitils,建议使用setuptools。
最终选择distutils,setiptools可能需要单独安装。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 利用python提供的自动化编译模块进行编译。编写一个编译文件setup.py
# 内容如下:(仅供参考,具体详细了解python自动化编译动态链接库文档)
from distutils.core import setup, Extension
# 生成一个扩展模块
test_swig_module = Extension('_test_swig', # 模块名称,必须要有下划线
sources=['test_swig_wrap.cxx', # 封装后的接口cxx文件
'test_swig.cpp'],
)
setup(name = 'test_swig', # 打包后的名称
version = '0.1',
author = 'SWIG Docs',
description = 'Simple swig pht from docs',
ext_modules = [test_swig_module], # 与上面的扩展模块名称一致
py_modules = ['test_swig'], # 需要打包的模块列表
)
python3 setup.py build
[root@ubuntu0006:/media/hankin/vdb/swig/test/build] #ll
总用量 24
drwxr-xr-x 6 root root 4096 7月 27 15:59 ./
drwxr-xr-x 3 root root 4096 7月 27 15:58 ../
drwxr-xr-x 2 root root 4096 7月 27 15:56 lib.linux-x86_64-2.7/
drwxr-xr-x 2 root root 4096 7月 27 15:59 lib.linux-x86_64-3.6/
drwxr-xr-x 2 root root 4096 7月 27 15:56 temp.linux-x86_64-2.7/
drwxr-xr-x 2 root root 4096 7月 27 15:59 temp.linux-x86_64-3.6/
[root@ubuntu0006:/media/hankin/vdb/swig/test/build/lib.linux-x86_64-3.6] #ll
总用量 120
drwxr-xr-x 2 root root 4096 7月 27 15:59 ./
drwxr-xr-x 6 root root 4096 7月 27 15:59 ../
-rwxr-xr-x 1 root root 110400 7月 27 15:59 _test_swig.cpython-36m-x86_64-linux-gnu.so*
-rw-r--r-- 1 root root 2176 7月 27 10:24 test_swig.py
[root@ubuntu0006:/media/hankin/vdb/swig/test/build/lib.linux-x86_64-3.6] #python3
Python 3.6.5 (default, Feb 27 2021, 16:40:34)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import test_swig
>>> test_swig.add(3, 5)
8
>>> test_swig.sub(4, 3)
1
示例源代码见:D:\Github\Storage\others\swig。