入门
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'
这个答案似乎很好的解释了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
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无果。
用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