WinApi压缩、解压在python3
WinApi compression, decompression in python3
我有一个小型客户端应用程序,旨在 运行 在 windows 机器上。它是用 C/C++ 编写的(更多是用 C 编写的)。我想保持它的小,因此我宁愿不使用外部库并坚持在客户端使用 WinAPI。
另一方面,我有一个在 python3 中实现的后端服务器。在这里,我很乐意使用任何现有的库。现在我想添加压缩层以提高传输速度。我遇到的问题是WinAPI似乎只提供:
// source: https://docs.microsoft.com/en-us/windows/win32/cmpapi/using-the-compression-api
XPRESS
XPRESS with Huffman encoding
MSZIP
LZMS
这似乎是一种独特的 Microsoft 压缩算法实现,我在 python3 中找不到在服务器端解压缩数据的方法。
有什么我遗漏的吗?我很想听听一些解决方案:)
提前致谢
更新
我决定按照评论中的建议使用 zlib https://zlib.net/。建议使用 ctypes 的答案也很有趣,但不幸的是我的后端在 UNIX 系统上是 运行ning。
当我再次针对多线程 CRT(而非 DLL)编译我的客户端部分时,我遇到了一些问题,因为 zlib 正在与多线程 DLL 进行链接。如果有人遇到过此类问题,我在这里找到了一个很棒且超级简单的解决方案:https://yongweiwu.wordpress.com/2017/10/02/a-journey-of-purely-static-linking/
我会复制粘贴到这里:
zlib
This part requires a small change to the build script (for version 1.2.11).
I need to open win32\Makefile.msc and change all occurrences of ‘-MD’ to ‘-MT’.
Then these commands will work:
nmake -f win32\Makefile.msc zlib.lib
我找到了 this Python script, and reverse-engineered it to produce a quick library to handle WinAPI Compression/Decompression。基本上,您可以只使用 ctypes
并从 Python 调用 WinAPI。请记住,我没有对此进行广泛测试,但它应该给你一个很好的起点:)
编辑: 根据要求,我已经包含了 compress
和 decompress
函数的实现,以防链接断开。
def compress(UncompressedBuffer, UncompressedBufferSize, Format, Engine):
CompressedBuffer = (ctypes.c_ubyte * UncompressedBufferSize)()
CompressionFormatAndEngine = ctypes.c_uint16(Format.value | Engine.value)
CompressBufferWorkSpaceSize = ctypes.c_uint32()
CompressFragmentWorkSpaceSize = ctypes.c_uint32()
WorkSpace = (CompressFragmentWorkSpaceSize.value * ctypes.c_ubyte)()
FinalCompressedSize = ctypes.c_uint32()
WinDLLCall(RtlGetCompressionWorkSpaceSize,
CompressionFormatAndEngine,
ctypes.byref(CompressBufferWorkSpaceSize),
ctypes.byref(CompressFragmentWorkSpaceSize))
WinDLLCall(RtlCompressBuffer,
CompressionFormatAndEngine,
ctypes.byref(UncompressedBuffer),
ctypes.c_uint32(UncompressedBufferSize),
ctypes.byref(CompressedBuffer),
ctypes.c_uint32(UncompressedBufferSize),
UncompressedChunkSize,
ctypes.byref(FinalCompressedSize),
ctypes.byref(WorkSpace))
return CompressedBuffer, FinalCompressedSize
def decompress(CompressedBuffer, CompressedBufferSize, UncompressedBufferSize, Format):
UncompressedBuffer = (ctypes.c_ubyte * UncompressedBufferSize)()
FinalUncompressedSize = ctypes.c_uint32()
WinDLLCall(RtlDecompressBuffer,
Format,
ctypes.byref(UncompressedBuffer),
ctypes.c_uint32(UncompressedBufferSize),
ctypes.byref(CompressedBuffer),
ctypes.c_uint32(CompressedBufferSize),
ctypes.byref(FinalUncompressedSize))
return UncompressedBuffer, FinalUncompressedSize
WinAPI 函数使用以下代码加载:
import ctypes
RtlDecompressBuffer = ctypes.windll.ntdll.RtlDecompressBuffer
RtlCompressBuffer = ctypes.windll.ntdll.RtlCompressBuffer
RtlGetCompressionWorkSpaceSize = ctypes.windll.ntdll.RtlGetCompressionWorkSpaceSize
这里有一些其他有用的资源,如果您最终要修修补补的话:
我有一个小型客户端应用程序,旨在 运行 在 windows 机器上。它是用 C/C++ 编写的(更多是用 C 编写的)。我想保持它的小,因此我宁愿不使用外部库并坚持在客户端使用 WinAPI。
另一方面,我有一个在 python3 中实现的后端服务器。在这里,我很乐意使用任何现有的库。现在我想添加压缩层以提高传输速度。我遇到的问题是WinAPI似乎只提供:
// source: https://docs.microsoft.com/en-us/windows/win32/cmpapi/using-the-compression-api
XPRESS
XPRESS with Huffman encoding
MSZIP
LZMS
这似乎是一种独特的 Microsoft 压缩算法实现,我在 python3 中找不到在服务器端解压缩数据的方法。
有什么我遗漏的吗?我很想听听一些解决方案:)
提前致谢
更新
我决定按照评论中的建议使用 zlib https://zlib.net/。建议使用 ctypes 的答案也很有趣,但不幸的是我的后端在 UNIX 系统上是 运行ning。
当我再次针对多线程 CRT(而非 DLL)编译我的客户端部分时,我遇到了一些问题,因为 zlib 正在与多线程 DLL 进行链接。如果有人遇到过此类问题,我在这里找到了一个很棒且超级简单的解决方案:https://yongweiwu.wordpress.com/2017/10/02/a-journey-of-purely-static-linking/ 我会复制粘贴到这里:
zlib
This part requires a small change to the build script (for version 1.2.11).
I need to open win32\Makefile.msc and change all occurrences of ‘-MD’ to ‘-MT’.
Then these commands will work:
nmake -f win32\Makefile.msc zlib.lib
我找到了 this Python script, and reverse-engineered it to produce a quick library to handle WinAPI Compression/Decompression。基本上,您可以只使用 ctypes
并从 Python 调用 WinAPI。请记住,我没有对此进行广泛测试,但它应该给你一个很好的起点:)
编辑: 根据要求,我已经包含了 compress
和 decompress
函数的实现,以防链接断开。
def compress(UncompressedBuffer, UncompressedBufferSize, Format, Engine):
CompressedBuffer = (ctypes.c_ubyte * UncompressedBufferSize)()
CompressionFormatAndEngine = ctypes.c_uint16(Format.value | Engine.value)
CompressBufferWorkSpaceSize = ctypes.c_uint32()
CompressFragmentWorkSpaceSize = ctypes.c_uint32()
WorkSpace = (CompressFragmentWorkSpaceSize.value * ctypes.c_ubyte)()
FinalCompressedSize = ctypes.c_uint32()
WinDLLCall(RtlGetCompressionWorkSpaceSize,
CompressionFormatAndEngine,
ctypes.byref(CompressBufferWorkSpaceSize),
ctypes.byref(CompressFragmentWorkSpaceSize))
WinDLLCall(RtlCompressBuffer,
CompressionFormatAndEngine,
ctypes.byref(UncompressedBuffer),
ctypes.c_uint32(UncompressedBufferSize),
ctypes.byref(CompressedBuffer),
ctypes.c_uint32(UncompressedBufferSize),
UncompressedChunkSize,
ctypes.byref(FinalCompressedSize),
ctypes.byref(WorkSpace))
return CompressedBuffer, FinalCompressedSize
def decompress(CompressedBuffer, CompressedBufferSize, UncompressedBufferSize, Format):
UncompressedBuffer = (ctypes.c_ubyte * UncompressedBufferSize)()
FinalUncompressedSize = ctypes.c_uint32()
WinDLLCall(RtlDecompressBuffer,
Format,
ctypes.byref(UncompressedBuffer),
ctypes.c_uint32(UncompressedBufferSize),
ctypes.byref(CompressedBuffer),
ctypes.c_uint32(CompressedBufferSize),
ctypes.byref(FinalUncompressedSize))
return UncompressedBuffer, FinalUncompressedSize
WinAPI 函数使用以下代码加载:
import ctypes
RtlDecompressBuffer = ctypes.windll.ntdll.RtlDecompressBuffer
RtlCompressBuffer = ctypes.windll.ntdll.RtlCompressBuffer
RtlGetCompressionWorkSpaceSize = ctypes.windll.ntdll.RtlGetCompressionWorkSpaceSize
这里有一些其他有用的资源,如果您最终要修修补补的话: