使用与系统不同版本的zlib.so进行Python cdll导入

1 投票
1 回答
637 浏览
提问于 2025-04-16 13:00

大家好,

我正在尝试修改 zlib 并测试一些行为,所以我写了 mylib.cmylib.h。这两个文件是用来包装 zlib 函数的,像 InflateInit2() 这样的函数可以在里面调用。我用以下命令来编译和链接:

gcc -g -Wall -Werror -c -std=c99 -I./zlib-1.2.5 -I./ -fPIC mylib.c 
gcc -shared mylib.o -o mylib.so

然后我用下面的方式把它导入到 Python 中:

mylib = cdll.LoadLibrary(os.getcwd() + '/mylib.so')

我需要一个不同于我系统上安装的 zlib 版本,所以我从源代码下载并编译了一个不同的版本(因为在系统上安装的那个版本不稳定)。现在我遇到的问题是,我在自定义编译的 zlib 源文件中所做的更改,在使用 mylib 的 Python 中并没有反映出来。Python(或者可能是我编译 mylib.so 的方法)似乎在使用系统上那个版本的 zlib。有没有办法指定“正确”的 zlib.so 版本呢?

1 个回答

1

我认为Python的源代码是静态链接了一个打包好的zlib库。如果你想让Python使用你自己的版本,可能需要下载Python的源代码,然后构建一个自定义的解释器,把你修改过的zlib库替换进去。

# system python static lib bundles the zlibmodule.o code
ares% nm -ao /usr/lib/libpython2.6.a|grep initzlib
/usr/lib/libpython2.6.a:zlibmodule.o:0000000000000000 T initzlib

更新:谢谢你提供的额外信息,我明白你想做什么了。

把你自定义的zlib放在一个共享对象里是行不通的,正如你发现的那样。你需要直接通过cdll.LoadLibrary()返回的共享对象句柄来调用你自定义的zlib函数。你还需要通过扩展ctypes.Structure来模拟一个z_stream结构。

下面是一个部分示例,应该能帮助你入门:

from ctypes import *

class z_stream(Structure):

    _fields_ = [
        ('next_in', c_char_p),
        ('avail_in', c_uint),
        ('total_in', c_ulong),
        # finish adding all fields in the z_stream struct..
        ]

stream = z_stream()

zlib = cdll.LoadLibrary('./zlib-1.2.5/libz.so.1')
ret = zlib.deflateInit_(stream, 1, "1.2.5", sizeof(stream))
print ret

撰写回答