Python中如何调用依赖其他动态库的C语言.SO文件
最近要做 SDK 测试,SDK 是由 C 语言封装成的,函数封装在了 .so动态库中,而且该动态库还依赖其他的第三方动态库,不知道该怎么调用,求助各位大神,给个 demo
ps: linux平台的库
#call_c.py
import ctypes
from ctypes import *
ll = ctypes.cdll.LoadLibrary
lib = ll("./libIFaceRecSDK.so")
单独调用就大概是上面这样子了,但 libIFaceRecSDK.so 这个动态库还依赖其他库,且带有头文件时,我该怎么调用啊??你们看,这个库还依赖以下的这多么的库,还有头文件!!求救!

Python中如何调用依赖其他动态库的C语言.SO文件
遇到这种情况,我的解决方法就是要么自己封装一个 C 模块给 py,要么 FFI。前者偏向调用复杂模块的时候,后者偏向调用简单模块。
另外这个依赖和你没多少关系,系统或者 libffi 会帮你解决。
给个 CFFI 参考链接。
https://eli.thegreenplace.net/2013/03/09/python-ffi-with-ctypes-and-cffi/
要调用依赖其他动态库的C语言.so文件,你需要确保所有依赖库都能被系统找到。这里给你一个完整的例子。
假设我们有一个C库libmylib.so,它依赖libdep.so。首先,你需要用ctypes加载它,但得先处理依赖。
1. 设置库路径
最直接的方法是在加载前,把依赖库所在的目录加到LD_LIBRARY_PATH环境变量里:
import os
import ctypes
# 添加依赖库路径
os.environ['LD_LIBRARY_PATH'] = '/path/to/deps:' + os.environ.get('LD_LIBRARY_PATH', '')
# 加载主库
lib = ctypes.CDLL('/path/to/libmylib.so')
2. 使用ctypes的加载选项
或者,在加载时指定RTLD_GLOBAL标志,这样依赖的符号对后续加载的库可见:
import ctypes
# RTLD_GLOBAL让依赖的符号全局可见
lib = ctypes.CDLL('/path/to/libmylib.so', mode=ctypes.RTLD_GLOBAL)
3. 先显式加载依赖库 你也可以手动先加载所有依赖:
import ctypes
# 先加载依赖库
ctypes.CDLL('/path/to/libdep.so', mode=ctypes.RTLD_GLOBAL)
# 再加载主库
lib = ctypes.CDLL('/path/to/libmylib.so')
# 现在可以调用函数了
result = lib.my_function()
4. 使用cdll.LoadLibrary
ctypes.cdll.LoadLibrary和CDLL类似,但能更好地处理依赖:
import ctypes
# 加载依赖
dep_lib = ctypes.cdll.LoadLibrary('/path/to/libdep.so')
# 加载主库
main_lib = ctypes.cdll.LoadLibrary('/path/to/libmylib.so')
完整示例
这里是一个更完整的例子,假设libmylib.so有个函数add:
import os
import sys
import ctypes
# 添加库路径
lib_path = '/path/to/libs'
os.environ['LD_LIBRARY_PATH'] = lib_path + ':' + os.environ.get('LD_LIBRARY_PATH', '')
# 加载库
try:
lib = ctypes.CDLL(os.path.join(lib_path, 'libmylib.so'))
except OSError as e:
print(f"加载失败: {e}")
sys.exit(1)
# 设置函数参数和返回类型
lib.add.argtypes = [ctypes.c_int, ctypes.c_int]
lib.add.restype = ctypes.c_int
# 调用函数
result = lib.add(3, 4)
print(f"结果: {result}")
关键点
- 确保所有
.so文件都有执行权限。 - 如果库有C++代码,可能需要
extern "C"来避免名称修饰。 - 用
ldd /path/to/libmylib.so检查依赖是否都满足。
总结
设置好库路径,用ctypes按依赖顺序加载就行。
/尴尬,不会 C 语言,现在手里就一份 SDK 内置函数文档,还有些库文件,头文件,我要做的就是用 python 调 SDK 中的这些方法;
我看一下这个 FFI,谢谢哈
Cffi 了解一下
调不通啊,报错
我觉得有点像比较初级的库路径问题。可能是你的 LD_LIBRARY 设置有些问题。
一般做这种工作的步骤大概是:
1、先写个 C 的程序,简单调用下 SDK 功能。如果 C 程序链接、运行有问题,那就及时解决。
2、C 程序搞定后,再弄成 python 库。
一般来说,库都会依赖不少第三方和系统库。这部分依赖,一般做的好的 SDK 是无需关心的。只要能搜索到就可以。做的不好的 SDK,也应该可以在步骤 1 解决掉。
参考下?
http://oi.0w0.io/2018/01/05/Ubuntu-16-04-Python3-%E9%85%8D%E7%BD%AESQLite3-%E7%9A%84-icu-%E5%88%86%E8%AF%8D/#more
看报错像是路径有问题,但我代码跟 so 就在同级目录下啊,不该是路径问题啊
函数名,入参,出参,都有文档,可现在首要是调不通 so
undefined symbol: _ZN6apache6thrift12GlobalOutputE
表示的是找不到_ZN6apache6thrift12GlobalOutputE 这个函数,这个函数可能是哪个 so 中引用了,但是你系统里面没有。
google 一下这个函数大概是来自这些 so 文件
/usr/lib64/libthriftnb.so.0.0.0
/usr/lib/libthriftz-1.0.0-dev.so
所以你得看你系统是否安装了 libthrift ?或者版本是否正确?
_ZN6apache6thrift12GlobalOutputE 不出意外应该是来自 Apache Thrift 的库的 symbol.LZ 你 Apache Thrift 装了没?
人家说的是你那个库的依赖库没配置好,你为什么要强调你的"代码怎么着怎么着"…
pybind11 了解一下
lib 下有这个库 libthrift.so
不过,目录有什么要求吗?我是从别的地方拷过来的
Linux 默认不会搜索工作目录这样,如果 so 不是在 /usr/lib 或者 /lib 这样的地方,那么就需要你指定路径。
可以修改 /etc/ld.so.conf 这样来加载,但是既然缺少库,用包管理安装一下不是更好么?
我试过绝对路径,也是还是提示:undefined symbol: _ZN6apache6thrift12GlobalOutputE <br>from cffi import FFI<br><br>ffi = FFI()<br><br># ffi.cdef()<br>lib_IOTCAPIs = ffi.dlopen("/home/install/linux/x86_64/lib/<a target="_blank" href="http://libthrift.so" rel="nofollow noopener">libthrift.so</a>")<br>lib_IOTCAPIs = ffi.dlopen("/home/lib/cpu/<a target="_blank" href="http://libIFaceRecSDK.so" rel="nofollow noopener">libIFaceRecSDK.so</a>")<br>print('Loaded lib {0}'.format(lib))<br>
那只能说明这个函数可能不在这个 so 文件里,再去检查这个库有没有其他的 so 文件吧。
export LD_LIBRARY_PATH=/home/install/linux/x86_64/lib:$LD_LIBRARY_PATH
都说啦~写个简单 c 程序。调试通了,再跑 python。这样就能排除库本身问题。善用 readelf 之类的工具,导出引用表看看。
当然,如果已经通了,那就实验下 LD_LIBRARY
加载通了,但调里边 C 的方法,提示 AttributeError: function
你以前尝试过调用 c 的库没,如果没有的话,建议你写个 hello world 试试。
我大概猜到你啥问题了,不过还是建议你先自己试试。
以前用 python 调用过 C,调通了的
求告之,快被开除了
不好意思 可能是我理解错了


