Всем известен архиватор 7ZIP. Основа его ценности - метод сжатия lzma (улучшенная и оптимизированная версия алгоритма LZ77). Появилась необходимость использовать его в своей программе. Изучил страницу http://7-zip.org.ua/ru/sdk.html. Скачал это SDK. Собрал lzma.dll. Пытаюсь работать с ней через LoadLibrary/GetProcAddress. По идее мне всего-то и нужны реализации функций LzmaCompress/LzmaUncompress из этой либы, но проблема в том, что в таблице экспорта lzma.dll есть только: CreateObject GetMethodProperty GetNumberOfMethods То есть по идее, то, что я собрал - какой-то wrapper на эту либу и соответственно вызовы GetProcAddress на LzmaCompress/LzmaUncompress проваливаются. Пишу на WINAPI/С++. Если кто сталкивался с использованием LZMA в своём приложении, обладает какими-то тематическими исходниками, обладает "нормальной" версией DLL, или может поддать пинка в нужном для осмысления направлении - плиз, помогите разобраться с работой этой либы.
В LZMA,txt в корне СДК вроде есть описание How To USE Сам собирать не пробовал но пишут что ее чуть ли не собирать по разному надо в зависимости от того как юзать собираешься - щас попробую )) Посмотри тут \lzma\CPP\7zip\UI\Client7z\Client7z.cpp В main() пример использования
Угу, спасибо, Спайд. Там всё через COM-интерфейсы сделано, что для меня не есть гуд. Решил взять из SDK только LzmaDec.h, LzmaDec.c и Types.h. Ну то есть только реализацию алгоритма декомпрессии покопался в исходниках, наваял тестовый код, который должен был бы из памяти в память распаковать кое-какой файл, но проблема в том, что функция возвращает либо SZ_OK и пустой результат, либо SZ_ERROR_DATA и какой-то мусор. Ночью, как буду дома выложу тестовый код сюда, посмотри плиз, может поймёшь где я лажаю.
Ок, Спайд, ещё раз спасибо. Попробую прикурочить аплиб к приложению. В свою очередь выкладываю злосчастный исходник с LZMA memory to memory распаковщиком. Файлы проекта, собранные под 2003 студией лежат тут: http://groundhog.ru/lzma_test.zip Ниже привожу исходник. Постарался всё откоментировать, чтобы вам удобнее было понять. Может кому что бросится в глаза, и вы прольёте свет на то, где я лажаю, мне уже ничего не лезет в голову. Code: /* Работать будем с файлом test.7z. Архив содержит в себе всего один файл test.txt, который в свою очередь содержит строчку ASCII-текста "This is a simple text file! ;)". Метод сжатия: LZMA Формат архива: 7z Уровень сжатия: нормальный Вытяжка из lzma.txt Single-call Decompressing ------------------------- When to use: RAM->RAM decompressing Compile files: LzmaDec.h + LzmaDec.c + Types.h Compile defines: no defines Memory Requirements: - Input buffer: compressed size - Output buffer: uncompressed size - LZMA Internal Structures: state_size (16 KB for default settings) Interface: int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); In: dest - output data destLen - output data size src - input data srcLen - input data size propData - LZMA properties (5 bytes) propSize - size of propData buffer (5 bytes) finishMode - It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). You can use LZMA_FINISH_END, when you know that current output buffer covers last bytes of stream. alloc - Memory allocator. Out: destLen - processed output size srcLen - processed input size Output: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). If LZMA decoder sees end_marker before reaching output limit, it returns OK result, and output value of destLen will be less than output buffer size limit. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ #include <windows.h> // Подключаем windows-говнище extern "C" { #include "LzmaDec.h" // Подключаем LZMA-говнище (только метод распаковки) #include "Types.h" // Подключаем LZMA-говнище (определение типов) } // Мой макрос. Показывает описание последней ошибки согласно GetLastError() #define SHOW_LAST_ERROR() \ { \ LPVOID lpMsgBuf; \ FormatMessage( \ FORMAT_MESSAGE_ALLOCATE_BUFFER | \ FORMAT_MESSAGE_FROM_SYSTEM | \ FORMAT_MESSAGE_IGNORE_INSERTS, \ NULL, \ GetLastError(), \ 0, \ (LPTSTR) &lpMsgBuf, \ 0, \ NULL \ ); \ MessageBox(NULL, (LPCTSTR)lpMsgBuf, TEXT("Error"), MB_OK | MB_ICONERROR); \ LocalFree(lpMsgBuf); \ } // Объявление прототипов функций, основное описание ниже VOID *MyAlloc (size_t); VOID MyFree (VOID *); // Определяем два указателя на функции-враперы. Один указатель на врапер // выделения памяти, второй - указатель на врапер освобождения памяти static void *SzAlloc(VOID *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(VOID *p, VOID *address) { p = p; MyFree(address); } // Структурка (глобальная), описывающая врапер выделения и освобождения памяти static ISzAlloc g_Alloc = { SzAlloc, SzFree }; // Функция выделения заданного числа байт памяти VOID *MyAlloc (size_t size) { return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);; } // Функция освобождения выделеного блока памяти VOID MyFree (VOID *address) { VirtualFree(address, 0, MEM_RELEASE); } // Функция-реализация алгоритма распаковки LZMA INT LzmaUncompress(UCHAR *dest, size_t *destLen, const UCHAR *src, size_t *srcLen, const UCHAR *props, size_t propsSize) { ELzmaStatus status; return LzmaDecode(dest, destLen, src, srcLen, props, (UINT)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); } INT WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, INT nCmdShow) { TCHAR szSomeBuff[1024] = {0}; // Открываем файл на чтение HANDLE hFile = CreateFile(TEXT("test.7z"), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (INVALID_HANDLE_VALUE == hFile) { SHOW_LAST_ERROR(); return ERROR_FILE_NOT_FOUND; } // Получаем размер этого файла DWORD dwLowFileSize = 0, dwHighFileSize = 0; dwLowFileSize = GetFileSize(hFile, &dwHighFileSize); if (dwHighFileSize != NULL && dwLowFileSize == INVALID_FILE_SIZE && GetLastError != NO_ERROR) { SHOW_LAST_ERROR(); return ERROR_FILE_INVALID; } LONG nFileSize = MAKELONG(dwLowFileSize, dwHighFileSize); // Показываем информацию о размере файла ZeroMemory(szSomeBuff, 1024); wsprintf(szSomeBuff, TEXT("Размер целевого файла: %10d байт"), nFileSize); MessageBox(NULL, szSomeBuff, TEXT("Debug"), MB_OK); // Выделяем память необходимого объёма LPVOID lpFileInputData = MyAlloc(nFileSize); if (lpFileInputData == NULL) { SHOW_LAST_ERROR(); return ERROR_GEN_FAILURE; } DWORD dwBytesRead = 0; // Читаем файл в память BOOL bResult = ReadFile(hFile, lpFileInputData, nFileSize, &dwBytesRead, NULL); if (!bResult) { SHOW_LAST_ERROR(); return ERROR_GEN_FAILURE; } // Показываем информацию о количестве прочитанных байт ZeroMemory(szSomeBuff, 1024); wsprintf(szSomeBuff, TEXT("Из файла считано: %10d байт"), dwBytesRead); MessageBox(NULL, szSomeBuff, TEXT("Debug"), MB_OK); // Буфер для хранения распакованных данных. 16Кб хватит? size_t nOutputDataLen = 16384; LPVOID lpFileOutputData = MyAlloc(nOutputDataLen); if (lpFileOutputData == NULL) { SHOW_LAST_ERROR(); return ERROR_GEN_FAILURE; } nFileSize = nFileSize - LZMA_PROPS_SIZE; // Вызов функции распаковки bResult = LzmaUncompress( (UCHAR *)lpFileOutputData, // Буфер куда будет распакован файл &nOutputDataLen, // Длина буфера (UCHAR *)lpFileInputData + LZMA_PROPS_SIZE + 1, // Указатель на данные файла (отступаем ZMA_PROPS_SIZE байт от начала - это заголовок) (size_t *) &nFileSize, // Размер данных (без учёта заголовка) (UCHAR *)lpFileInputData, // Указатель на заголовок LZMA_PROPS_SIZE // Размер заголовка ); ZeroMemory(szSomeBuff, 1024); // Анализируем значение, которое вернула функция switch (bResult) { case SZ_OK : wsprintf(szSomeBuff, TEXT("Функция вернула: %s"), TEXT("SZ_OK")); break; case SZ_ERROR_DATA : wsprintf(szSomeBuff, TEXT("Функция вернула: %s"), TEXT("SZ_ERROR_DATA")); break; case SZ_ERROR_MEM : wsprintf(szSomeBuff, TEXT("Функция вернула: %s"), TEXT("SZ_ERROR_MEM")); break; case SZ_ERROR_UNSUPPORTED : wsprintf(szSomeBuff, TEXT("Функция вернула: %s"), TEXT("SZ_ERROR_UNSUPPORTED")); break; case SZ_ERROR_INPUT_EOF : wsprintf(szSomeBuff, TEXT("Функция вернула: %s"), TEXT("SZ_ERROR_INPUT_EOF")); break; } MessageBox(NULL, szSomeBuff, TEXT("Debug"), MB_OK); // Показываем результат распаковки ZeroMemory(szSomeBuff, 1024); wsprintf(szSomeBuff, TEXT("Буфер распаковки: %s"), lpFileOutputData); MessageBox(NULL, szSomeBuff, TEXT("Debug"), MB_OK); return 0; }
Вот тебе длл с 2мя нужными тебе методами http://www.sendspace.com/file/dbzpfb Юзай либо через HMODULE hLib = LoadLibrary("lzma.dll"); *(FARPROC*)&Uncompress= GetProcAddress(hLib,LzmaUncompress); *(FARPROC*)&Compress= GetProcAddress(hLib,LzmaCompress); (Параметры описаны в LzmaLib.h) Ну либо подруби C,h файлы из сдк. Либу возьми скомпилив вот это lzma\C\LzmaLib\LzmaLib.dsw