未加星标

Python-SWIG 初探以及其 gdb 调试

字体大小 | |
[开发(python) 所属分类 开发(python) | 发布者 店小二05 | 时间 2017 | 作者 红领巾 ] 0人收藏点击收藏

SWIG is used with different types of target languages including common scripting languages such as javascript, Perl,php, python, Tcl and Ruby.

上面那段是 SWIG 的官网介绍,简单地说,SWIG 是一个用于 C/C++ 和高层脚本语言交互的工具。脚本语言在 SWIG 的辅助下可以直接调 C/C++ 的程序。

简单试了一下 SWIG 在 Python 里面的用法,然后测试了一下 gdb 以及 VS 的远程调试 (红红火火恍恍惚惚,其实想记录的重点是这个)。

以下内容均在 WSL 里面完成。

Python-SWIG

直接 apt-get 把 SWIG 装上,然后就可以开始瞎搞了。

首先随便写个 C 的函数

官方的文档里面用的是个简单的阶乘的例子,这里也用这个好了。

cfact.h

intfact(intn);

cfact.c

#include"cfact.h" intfact(intn) { if (n < 0) return 0; else if (n == 0) return 1; else return n * fact(n-1); } 写 SWIG 部分的内容,并且生成对应的封装代码

创建一个 SWIG 的文件:

cfact.i

%module cfact %{ #defineSWIG_FILE_WITH_INIT #include"cfact.h" %} intfact(intn);

然后用 swig 命令生成封装代码:

$ swig -python cfact.i

调用完了之后会生成两个新的文件 cfact.py 以及 cfact_wrap.c 。

编译生成 Python 模块

Python 与 C/C++ 的交互是以模块的方式进行的,C/C++ 代码编译生成运行库之后,以模块的方式链接到 Python 的运行时中。

Python 自带一个 distutils 工具,用于创建扩展模块,写一个配置文件:

setup.py

from distutils.core import setup, Extension cfact_module = Extension('_cfact', sources=['cfact_wrap.c', 'cfact.c'], ) setup (name = 'cfact', version = '0.1', author = "Chen Fan", description = """Simple swig test""", ext_modules = [cfact_module], py_modules = ["cfact"], )

在目录下执行:

$ python setup.py build

编译得到完整的 Python 模块。

$ python setup.py build running build running build_py creating build creating build/lib.linux-x86_64-2.7 copying cfact.py -> build/lib.linux-x86_64-2.7 running build_ext building '_cfact' extension creating build/temp.linux-x86_64-2.7 x86_64-linux-gnu-gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c cfact_wrap.c -o build/temp.linux-x86_64-2.7/cfact_wrap.o x86_64-linux-gnu-gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c cfact.c -o build/temp.linux-x86_64-2.7/cfact.o x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -D_FORTIFY_SOURCE=2 -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security build/temp.linux-x86_64-2.7/cfact_wrap.o build/temp.linux-x86_64-2.7/cfact.o -o build/lib.linux-x86_64-2.7/_cfact.so

可以看到 cfact_wrap.c 和 cfact.c 首先被编译成 build/temp.linux-x86_64-2.7/ 目录下的 cfact_wrap.o 和 cfact.o 两个文件。

之后再编译成一个完整的 _cfact.so 运行库。

切到 build/lib.linux-x86_64-2.7/ 目录下就能用 Python 测试啦:

# jcf @ J-CF-YOGA in ~/swig_test [21:36:17] $ cd build/lib.linux-x86_64-2.7 # jcf @ J-CF-YOGA in ~/swig_test/build/lib.linux-x86_64-2.7 [21:41:45] $ python Python 2.7.6 (default, Oct 26 2016, 20:30:19) [GCC 4.8.4] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import cfact >>> cfact.fact(5) 120 >>> 上 gdb 调试

Python 进程是已经在运行了的,要用 gdb 调就只能附加上进程号来启动,可以在 Python 里面 import os 然后用 os.getpid() 获取进程号,或者用 top/htop 啥的直接看一下 Python 的进程号,然后在 gdb 里面启动即可。

$ gdb -p pid

gdb 正常启动,然后这时候可能会报找不到库的调试信息的错误,直接添加 fact 的断点会加不上。用 info sharedlibrary 命令看一下现在追踪到的库信息:

(gdb) info sharedlibrary From To Syms Read Shared Object Library 0x00007fa4d2be59f0 0x00007fa4d2bf2471 Yes /lib/x86_64-linux-gnu/libpthread.so.0 0x00007fa4d282f520 0x00007fa4d2974183 Yes /lib/x86_64-linux-gnu/libc.so.6 0x00007fa4d2600ed0 0x00007fa4d26019ce Yes /lib/x86_64-linux-gnu/libdl.so.2 0x00007fa4d23f0f10 0x00007fa4d23f1804 Yes /lib/x86_64-linux-gnu/libutil.so.1 0x00007fa4d21d1e00 0x00007fa4d21e1bf8 Yes (*) /lib/x86_64-linux-gnu/libz.so.1 0x00007fa4d1ec5610 0x00007fa4d1f34056 Yes /lib/x86_64-linux-gnu/libm.so.6 0x00007fa4d2e00ae0 0x00007fa4d2e1b490 Yes /lib64/ld-linux-x86-64.so.2 0x00007fa4d1b32720 0x00007fa4d1b33ef6 Yes (*) /usr/lib/python2.7/lib-dynload/readline.x86_64-linux-gnu.so 0x00007fa4d18f30d0 0x00007fa4d1913ee5 Yes (*) /lib/x86_64-linux-gnu/libreadline.so.6 0x00007fa4d16bc3d0 0x00007fa4d16c8028 Yes (*) /lib/x86_64-linux-gnu/libtinfo.so.5 No ./_cfact.so (*): Shared library is missing debugging information.

_cfact.so 由于不在 gdb 的默认库搜索路径下,所以找不到,需要手动加上路径。

关于 gdb 的库搜索策略,参见 这篇博文 。

这里简单地在 solib-search-path 里面加上 _cfact.so 的位置就好啦:

(gdb) show solib-search-path The search path for loading non-absolute shared library symbol files is . (gdb) set solib-search-path :/home/jcf/swig_test/build/lib.linux-x86_64-2.7/ Reading symbols from /home/jcf/swig_test/build/lib.linux-x86_64-2.7/_cfact.so...done. Loaded symbols for /home/jcf/swig_test/build/lib.linux-x86_64-2.7/_cfact.so (gdb)

可以看到 set 完之后 _cfact.so 已经自动被载入完成了。

这时候在 fact 这个函数上设断点就能够正常找到了:

(gdb) break fact Breakpoint 1 at 0x7fa4d14a3020: file cfact.c, line 5. (gdb) c Continuing.

在 Python 窗口里面再调一次 cfact.fact 函数,gdb 成功断在了这里:

Breakpoint 1, fact ([email protected]=6) at cfact.c:5 5 if (n < 0) return 0; (gdb) l 1 #include "cfact.h" 2 3 int fact(int n) 4 { 5 if (n < 0) return 0; 6 else if (n == 0) return 1; 7 else return n * fact(n-1); 8 }(gdb)

调用栈也是比较清晰的,Python 通过生成的封装文件 cfact_wrap.c 最后才调用到最初写的 cfact.c 文件中去。

(gdb) bt #0 fact ([email protected]=6) at cfact.c:5 #1 0x00007fa4d14a1c45 in _wrap_fact (self=<optimized out>, args=<optimized out>) at cfact_wrap.c:3119 #2 0x0000000000523f6d in PyEval_EvalFrameEx () #3 0x0000000000567d14 in ?? () #4 0x0000000000465a2d in PyRun_InteractiveOneFlags () #5 0x0000000000465b49 in PyRun_InteractiveLoopFlags () #6 0x00000000004661fe in PyRun_AnyFileExFlags () #7 0x0000000000466d92 in Py_Main () #8 0x00007fa4d2831f45 in __libc_start_main (main=0x466e50 <main>, argc=1, argv=0x7fffcd30af38, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffcd30af28) at libc-start.c:287 #9 0x0000000000577c2e in _start ()

本文开发(python)相关术语:python基础教程 python多线程 web开发工程师 软件开发工程师 软件开发流程

主题: C++PythonPHPPerlJavaRuby其实TI
分页:12
转载请注明
本文标题:Python-SWIG 初探以及其 gdb 调试
本站链接:http://www.codesec.net/view/530670.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 开发(python) | 评论(0) | 阅读(14)