Python 使用ctypes/cffi解析循环共享对象依赖关系
我想使用Python 使用ctypes/cffi解析循环共享对象依赖关系,python,ctypes,circular-dependency,dlopen,python-cffi,Python,Ctypes,Circular Dependency,Dlopen,Python Cffi,我想使用cffi(如果必须的话,甚至ctypes)从Linux上的Python 3访问C ABI。该API由许多.so文件实现(我们称它们为libA.so,libB.so和libC.so),这样libA包含主要导出函数,其他lib为libA提供支持 现在,libA依赖于libB,libB依赖于libC。然而,有一个问题。有一个由libA定义的全局数组,libC希望它存在。所以libC实际上依赖于libA——一种循环依赖。尝试使用相当于dlopen的cffi或CTAG加载libA会导致libB和l
cffi
(如果必须的话,甚至ctypes
)从Linux上的Python 3访问C ABI。该API由许多.so
文件实现(我们称它们为libA.so
,libB.so
和libC.so
),这样libA
包含主要导出函数,其他lib为libA
提供支持
现在,libA
依赖于libB
,libB
依赖于libC
。然而,有一个问题。有一个由libA
定义的全局数组,libC
希望它存在。所以libC
实际上依赖于libA
——一种循环依赖。尝试使用相当于dlopen
的cffi或CTAG加载libA
会导致libB
和libC
中缺少符号,但尝试加载libC
首先会导致缺少数组的错误(在libA
中)
因为它是一个变量,而不是一个函数,所以RTLD_LAZY选项在这里似乎不适用
奇怪的是,lddliba.so
没有将libB
或libC
显示为依赖项,所以我不确定这是否是问题的一部分。我认为这依赖于任何与这些库链接的程序来显式地指定它们
有没有办法绕过这个问题?一个想法是创建一个新的共享对象(比如,“all.so”),它依赖于libA
、libB
和libC
,这样dlopen(“all.so”)
可以一次性加载它所需的所有内容,但我也无法让它工作
处理这种情况的最佳策略是什么?事实上,我试图访问的ABI相当大,可能有20-30个共享对象文件。这(如果我理解正确的话)是Nix上的一个非常正常的用例,应该可以毫无问题地运行
在处理与ctypes()相关的问题时,解决这些问题的最佳(通用)方法是:
- 编写一个(小型)C应用程序来完成所需的工作(当然,工作正常)
- 然后才转到ctypes(基本上这是翻译上述应用程序)
- 定义.h:
#pragma一次 #包括 #定义PRINT\u MSG\u 0()printf(“从C:[%s](%d)-[%s]\n”,\uuuu文件\uuuuuuuuuu,\uuuuu行\uuuuuuu,\uuuuuuu函数\uuuuu)
- libC:
- libC.h:
#pragma一次 大小函数();
- libC.c:
#包括“defines.h” #包括“libC.h” #包括“libA.h” 大小函数(){ 打印消息0(); 对于(大小i=0;i
- libC.h:
- libB:
- libB.h:
#pragma一次 大小函数b();
- libB.c:
#包括“defines.h” #包括“libB.h” #包括“libC.h” 大小函数b(){ 打印消息0(); 返回func(); }
- libB.h:
- libA:
- libA.h:
#pragma一次 #定义数组_DIM 3 外部字符字符[ARRAY_DIM]; 大小函数();
- libA.c:
#包括“defines.h” #包括“libA.h” #包括“libB.h” 字符数组[ARRAY_DIM]={'A','B','C'}; 大小函数(){ 打印消息0(); 返回funcB(); }
- libA.h:
- code.py:
#/usr/bin/env蟒蛇3 导入系统 从ctypes导入CDLL\ c_尺寸 DLL=“./libA.so” def main(): lib_a=CDLL(DLL) func_a=lib_a.funcA func_a.restype=c_size\u t ret=func_a() 打印({:s}返回{:d})。格式(func_a.\uu name_uu,ret)) 如果名称=“\uuuuu main\uuuuuuuu”: 打印(“Python{:s}on{:s}\n.”格式(sys.version,sys.platform)) main()
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q053327620]>ls
code.py定义.h libA.c libA.h libB.c libB.h libC.c libC.h
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q053327620]>gcc-fPIC-shared-o libC.so libC.c
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q053327620]>gcc-fPIC-shared-o libB.so libB.c-L-lC
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q053327620]>gcc-fPIC-shared-o libA.so libA.c-L-lB
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q053327620]>ls
code.py定义.h libA.c libA.h libA.so libB.c libB.h libB.so libC.c libC.h libC.h libC.so
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q053327620]>LD\u LIBRARY\u PATH=。ldd libC.so
linux vdso.so.1=>(0x00007ffdfb1f4000)
libc.so.6=>/lib/x86_64-linux-gnu/libc.so.6(0x00007f56dcf23000)
/lib64/ld-linux-x86-64.so.2(0x00007f56dd4ef000)
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q053327620]>LD\u LIBRARY\u PATH=。ldd libB.so
linux vdso.so.1=>(0x00007ffc2e7fd000)
libC.so=>。/libC.so(0x00007fdc90a9a000)
libc.so.6=>/lib/x86_64-linux-gnu/libc.so.6(0x00007fdc906d0000)
/lib64/ld-linux-x86-64.so.2(0x00007fdc90e9e000)
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q053327620]>LD\u LIBRARY\u PATH=。利巴索酒店
linux vdso.so.1=>(0x00007ffd20d53000)
libB.so=>。/libB.so(0x00007fdbee95a000)
libc.so.6=>/lib/x86_64-linux-gnu/libc.so.6(0x00007fdbee590000)
libC.so=>。/libC.so(0x00007fdbee38e000)
/lib64/ld-linux-x86-64.so.2(0x00007fdbeed5e000)
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q053327620]>nm-S libC.so | grep charArray
乌查拉雷
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q053327620]>nm-S libA.so | grep charArray
0000000000 201030000000000000000三维字符集
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q053327620]>LD\u LIBRARY\u PATH=。python3代码.py
Python 3.5.2(默认值,2018年11月12日,13:43:14)
[GCC 5.4.0 20160609]在linux上
来自C:[libA