Сжатие WinApi, декомпрессия в python3 - PullRequest
1 голос
/ 07 мая 2020

У меня есть небольшое клиентское приложение, предназначенное для работы на 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.

Поскольку я компилирую свою клиентскую часть снова с многопоточной 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

1 Ответ

0 голосов
/ 08 мая 2020

Я нашел этот Python скрипт и перепроектировал его, чтобы создать быструю библиотеку для обработки WinAPI Compression / Decompression . По сути, вы можете просто использовать ctypes и вызывать WinAPI из Python. Имейте в виду, что я тщательно не тестировал это, но это должно дать вам довольно хорошее место для начала :)

EDIT: По запросу я включил реализации функции compress и decompress в случае, если ссылки когда-либо go не работают.

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

Вот некоторые другие полезные ресурсы, если вы в конечном итоге возитесь:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...