通过swig将C/C++代码暴露给python

37 篇文章 0 订阅
22 篇文章 0 订阅

入门

http://www.swig.org/Doc3.0/Introduction.html#Introduction

可以通过include头文件的方式去定义.i文件。这样大大方便了.i文件的书写。实验发现函数可以不用加extern。

%module example                                                                                                                                                                                                                                    
%{
    #include "example.h"
%}
%include "example.h"

遇到 'ImportError: dynamic module does not define init function'

https://stackoverflow.com/questions/50024581/c-program-swig-to-python-gives-importerror-dynamic-module-does-not-define-init

这个答案似乎很好的解释了import背后发生的行为。所以最后生成的动态库文件的名字一定要带下划线

但是奇怪的是当我删除example.py之后,我依然可以通过import _example去调用C/C++接口。

等有时间还要好好研究一下。https://docs.python.org/3.6/extending/

tianyxu@love_server1:~/swig/lazyintro$ ls
example.c  example.h  example.i  example.o  example.py  _example.so  example_wrap.c  example_wrap.o  __pycache__
tianyxu@love_server1:~/swig/lazyintro$ rm example.py
tianyxu@love_server1:~/swig/lazyintro$ python3
Python 3.6.9 (default, Jan 26 2021, 15:33:00) 
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'example'
>>> import _example
>>> _example.fact(5)
120
>>> 

遇到 Error: Syntax error - possibly a missing semicolon

https://stackoverflow.com/questions/28523496/syntax-error-when-include-opencv-core-hpp-in-swig

因为%include里面有嵌套include头文件,貌似嵌套里面的头文件必须要先%include进来。

遇到makefile error: opening dependency file .d/file_name.Td: No such file or directory

https://stackoverflow.com/questions/52192082/makefile-error-opening-dependency-file-d-file-name-td-no-such-file-or-directo

makefile一定要将生成对象所在的目录先建好。否则会报依赖错误。

遇到 import modulename报segmentation fault

https://swig-devel.narkive.com/kTeRO3Ln/import-error-in-python

https://www.cnblogs.com/sddai/p/10375979.html

尝试用gdb debug由segment fault产生的core文件无果。可以看到bt报了一个乱七八糟的错误

Core was generated by `python3.6 meta_dx1.py'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f8766cea269 in GlobalError::PushToStack() () from /usr/lib/x86_64-linux-gnu/libapt-pkg.so.5.0
(gdb) bt                       
#0  0x00007f8766cea269 in GlobalError::PushToStack() () from /usr/lib/x86_64-linux-gnu/libapt-pkg.so.5.0
#1  0x00007f8766d6e872 in pkgInitConfig(Configuration&) () from /usr/lib/x86_64-linux-gnu/libapt-pkg.so.5.0
#2  0x00007f876772bed8 in ?? () from /usr/lib/python3/dist-packages/apt_pkg.cpython-36m-x86_64-linux-gnu.so

尝试使用最新版本的swig无果。

尝试https://stackoverflow.com/questions/57064962/boost-python-own-module-throws-segmentation-fault-globalerrorpushtostack

用pkg-config添加编译和加载选项,还是没有用。

最后尝试使用python3.5的编译选项去代替python3.6的编译选项。

-I/usr/include/python3.6m替换为-I/usr/local/include/python3.5m

切换到python3.5之后在import的时候就没有segment fault的问题了(可见这个segment fault问题是由于不同版本的python引起的,应该是vendor给的.i文件依赖的某个python3.5的功能或者bug在python3.6的时候不见了,需要debug .i文件)

但是在import的时候

遇到了ImportError: ..undefined symbol: shm_open

这个是在连接的时候没有添加librt.so造成的。

通过添加编译选项-lrt解决。

最后总算可以成功将vendor driver暴露到python了。

有趣的是通过python3.5头文件编译最后生成的动态库不仅可以供给python3.5使用也可以供给python3.6使用

因此怀疑segmentation fault的问题是由于没有链接librt造成的

从新换回python3.6的编译选项,segment fault问题消失。

有时候往前多走几步才能发现问题的根源。。。

同一个原因:因为在编译链接动态库的时候没有链接这个动态库所依赖的librt,在不同python解释器import动态库的时候却有两种现象。

tianyxu@love_server1:/ws-tianyxu/metadx/sdk/python$ python3.6 meta_dx1.py 
Segmentation fault (core dumped)
tianyxu@love_server1:/ws-tianyxu/metadx/sdk/python$ python3.5 meta_dx1.py 
Traceback (most recent call last):
  File "meta_dx1.py", line 15, in <module>
    import _meta_dx1
ImportError: /ws-tianyxu/metadx/sdk/python/_meta_dx1.so: undefined symbol: shm_open

使用python3.6的头文件编译但是用python3.5解释器执行可以看到有合理的报错,但是python3.6解释器却报segmentation fault。

看上去像是python3.6解释器的一个bug。试一下最新版本的python3.9是否有这个问题。

python3.9解释器表现优秀,和python3.5解释器结果一致。似乎python3.9解释器修复了python3.6解释器引入的bug

tianyxu@love_server1:/ws-tianyxu/metadx/sdk/python$ python3.9 -i meta_dx1.py
Traceback (most recent call last):
  File "/ws-tianyxu/metadx/sdk/python/meta_dx1.py", line 15, in <module>
    import _meta_dx1
ImportError: /ws-tianyxu/metadx/sdk/python/_meta_dx1.so: undefined symbol: shm_open
>>>
tianyxu@love_server1:/ws-tianyxu/metadx/sdk/python$ python3.6 -i meta_dx1.py
Segmentation fault (core dumped)
tianyxu@love_server1:/ws-tianyxu/metadx/sdk/python$ python3.5 -i meta_dx1.py
Traceback (most recent call last):
  File "meta_dx1.py", line 15, in <module>
    import _meta_dx1
ImportError: /ws-tianyxu/metadx/sdk/python/_meta_dx1.so: undefined symbol: shm_open

嵌套动态库的链接

https://stackoverflow.com/questions/51839902/using-a-shared-library-in-another-shared-library

生成动态库的时候不会去检查有没有符号没有定义,在运行的时候/生成可执行文件时,才检查符号有没有定义。make sense。

https://stackoverflow.com/questions/10401059/how-to-use-librt-function-in-python

那么再考虑是否在python解释器里面先加载librt的符号,然后再加载meta_dx1(在链接的时候并不链接librt)

看看python3.5、python3.6、python3.9的表现

tianyxu@love_server1:/ws-tianyxu/metadx/sdk/python$ ls                                                                                                                  
core  mdx1_api_wrap.c  _meta_dx1.d  meta_dx1.py  _meta_dx1.so  __pycache__                                                                                                  
tianyxu@love_server1:/ws-tianyxu/metadx/sdk/python$ python3.6                                                                                                           
Python 3.6.9 (default, Jan 26 2021, 15:33:00)                                                                                                                         
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import meta_dx1
Segmentation fault (core dumped)
tianyxu@love_server1:/ws-tianyxu/metadx/sdk/python$ python3.6
Python 3.6.9 (default, Jan 26 2021, 15:33:00)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> ctypes.CDLL('librt.so', mode=ctypes.RTLD_GLOBAL)
<CDLL 'librt.so', handle d4adc0 at 0x7f154a388048>
>>> import meta_dx1
>>> meta_dx1.mdx1_
Display all 503 possibilities? (y or n)

python3.6不再有segmentation fault的问题了。

tianyxu@love_server1:/ws-tianyxu/metadx/sdk/python$ python3.5
Python 3.5.2 (default, May  8 2021, 03:32:38) 
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> ctypes.CDLL('librt.so', mode=ctypes.RTLD_GLOBAL)
<CDLL 'librt.so', handle 55750fcd1680 at 0x7f1a47cff5c0>
>>> import meta_dx1
>>> 
tianyxu@love_server1:/ws-tianyxu/metadx/sdk/python$ python3.9
Python 3.9.5 (default, May  8 2021, 10:53:57) 
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> ctypes.CDLL('librt.so', mode=ctypes.RTLD_GLOBAL)
<CDLL 'librt.so', handle 563cc744fbf0 at 0x7f3c076fac40>
>>> import meta_dx1

python3.5/3.9也不再有undefined symbol的问题。

相关命令

1. locate 定位可能因为没有updatedb没有查到,用find保险一点

2. pkg-config可以查看库的用于编译的信息,比如pkg-config --libs/--cflags。

3. ldd可以查看共享库的依赖

4. ulimit修改限定的core size之后可以得到segmentation fault产生的core文件用于debug

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值