如何在C++中使用LZMA SDK?

10

我在我的应用程序中使用LZMA SDK遇到了困难。

我想创建一种单文件压缩工具。我不需要任何目录支持,只需要LZMA2流。但是我不知道如何使用LZMA SDK来实现这个功能。

请问有人能给我一个关于如何在C++中使用LZMA SDK的小例子吗?


可能是7-Zip:有好的教程吗?的重复问题。 - Alex Reynolds
这里是否包含文档? - TerraOrbis
3个回答

5

我认为使用LZMA SDK是一个很好的小例子。

/* LzmaUtil.c -- Test application for LZMA compression  
2008-08-05  
Igor Pavlov  
public domain */   

#define _CRT_SECURE_NO_WARNINGS   

#include <stdio.h>   
#include <stdlib.h>   
#include <string.h>   

#include "../LzmaDec.h"   
#include "../LzmaEnc.h"   
#include "../Alloc.h"   

const char *kCantReadMessage = "Can not read input file";   
const char *kCantWriteMessage = "Can not write output file";   
const char *kCantAllocateMessage = "Can not allocate memory";   
const char *kDataErrorMessage = "Data error";   

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 };   

#define kInBufferSize (1 << 15)   
#define kOutBufferSize (1 << 15)   

unsigned char g_InBuffer[kInBufferSize];   
unsigned char g_OutBuffer[kOutBufferSize];   

size_t MyReadFile(FILE *file, void *data, size_t size)   
  { return fread(data, 1, size, file); }   

int MyReadFileAndCheck(FILE *file, void *data, size_t size)   
  { return (MyReadFile(file, data, size) == size); }   

size_t MyWriteFile(FILE *file, const void *data, size_t size)   
{   
  if (size == 0)   
    return 0;   
  return fwrite(data, 1, size, file);   
}   

int MyWriteFileAndCheck(FILE *file, const void *data, size_t size)   
  { return (MyWriteFile(file, data, size) == size); }   

long MyGetFileLength(FILE *file)   
{   
  long length;   
  fseek(file, 0, SEEK_END);   
  length = ftell(file);   
  fseek(file, 0, SEEK_SET);   
  return length;   
}   

void PrintHelp(char *buffer)   
{   
  strcat(buffer, "\nLZMA Utility 4.58 Copyright (c) 1999-2008 Igor Pavlov  2008-04-11\n"   
      "\nUsage:  lzma <e|d> inputFile outputFile\n"   
             "  e: encode file\n"   
             "  d: decode file\n");   
}   

int PrintError(char *buffer, const char *message)   
{   
  strcat(buffer, "\nError: ");   
  strcat(buffer, message);   
  strcat(buffer, "\n");   
  return 1;   
}   

int PrintErrorNumber(char *buffer, SRes val)   
{   
  sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);   
  return 1;   
}   

int PrintUserError(char *buffer)   
{   
  return PrintError(buffer, "Incorrect command");   
}   

#define IN_BUF_SIZE (1 << 16)   
#define OUT_BUF_SIZE (1 << 16)   

static int Decode(FILE *inFile, FILE *outFile, char *rs)   
{   
  UInt64 unpackSize;   
  int thereIsSize; /* = 1, if there is uncompressed size in headers */   
  int i;   
  int res = 0;   

  CLzmaDec state;   

  /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */   
  unsigned char header[LZMA_PROPS_SIZE + 8];   

  /* Read and parse header */   

  if (!MyReadFileAndCheck(inFile, header, sizeof(header)))   
    return PrintError(rs, kCantReadMessage);   

  unpackSize = 0;   
  thereIsSize = 0;   
  for (i = 0; i < 8; i++)   
  {   
    unsigned char b = header[LZMA_PROPS_SIZE + i];   
    if (b != 0xFF)   
      thereIsSize = 1;   
    unpackSize += (UInt64)b << (i * 8);   
  }   

  LzmaDec_Construct(&state);   
  res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);   
  if (res != SZ_OK)   
    return res;   
  {   
    Byte inBuf[IN_BUF_SIZE];   
    Byte outBuf[OUT_BUF_SIZE];   
    size_t inPos = 0, inSize = 0, outPos = 0;   
    LzmaDec_Init(&state);   
    for (;;)   
    {   
      if (inPos == inSize)   
      {   
        inSize = MyReadFile(inFile, inBuf, IN_BUF_SIZE);   
        inPos = 0;   
      }   
      {   
        SizeT inProcessed = inSize - inPos;   
        SizeT outProcessed = OUT_BUF_SIZE - outPos;   
        ELzmaFinishMode finishMode = LZMA_FINISH_ANY;   
        ELzmaStatus status;   
        if (thereIsSize && outProcessed > unpackSize)   
        {   
          outProcessed = (SizeT)unpackSize;   
          finishMode = LZMA_FINISH_END;   
        }   

        res = LzmaDec_DecodeToBuf(&state, outBuf + outPos, &outProcessed,   
            inBuf + inPos, &inProcessed, finishMode, &status);   
        inPos += (UInt32)inProcessed;   
        outPos += outProcessed;   
        unpackSize -= outProcessed;   

        if (outFile != 0)   
          MyWriteFile(outFile, outBuf, outPos);   
        outPos = 0;   

        if (res != SZ_OK || thereIsSize && unpackSize == 0)   
          break;   

        if (inProcessed == 0 && outProcessed == 0)   
        {   
          if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)   
            res = SZ_ERROR_DATA;   
          break;   
        }   
      }   
    }   
  }   

  LzmaDec_Free(&state, &g_Alloc);   
  return res;   
}   

typedef struct _CFileSeqInStream   
{   
  ISeqInStream funcTable;   
  FILE *file;   
} CFileSeqInStream;   

static SRes MyRead(void *p, void *buf, size_t *size)   
{   
  if (*size == 0)   
    return SZ_OK;   
  *size = MyReadFile(((CFileSeqInStream*)p)->file, buf, *size);   
  /*  
  if (*size == 0)  
    return SZE_FAIL;  
  */   
  return SZ_OK;   
}   

typedef struct _CFileSeqOutStream   
{   
  ISeqOutStream funcTable;   
  FILE *file;   
} CFileSeqOutStream;   

static size_t MyWrite(void *pp, const void *buf, size_t size)   
{   
  return MyWriteFile(((CFileSeqOutStream *)pp)->file, buf, size);   
}   

static SRes Encode(FILE *inFile, FILE *outFile, char *rs)   
{   
  CLzmaEncHandle enc;   
  SRes res;   
  CFileSeqInStream inStream;   
  CFileSeqOutStream outStream;   
  CLzmaEncProps props;   

  enc = LzmaEnc_Create(&g_Alloc);   
  if (enc == 0)   
    return SZ_ERROR_MEM;   

  inStream.funcTable.Read = MyRead;   
  inStream.file = inFile;   
  outStream.funcTable.Write = MyWrite;   
  outStream.file = outFile;   

  LzmaEncProps_Init(&props);   
  res = LzmaEnc_SetProps(enc, &props);   

  if (res == SZ_OK)   
  {   
    Byte header[LZMA_PROPS_SIZE + 8];   
    size_t headerSize = LZMA_PROPS_SIZE;   
    UInt64 fileSize;   
    int i;   

    res = LzmaEnc_WriteProperties(enc, header, &headerSize);   
    fileSize = MyGetFileLength(inFile);   
    for (i = 0; i < 8; i++)   
      header[headerSize++] = (Byte)(fileSize >> (8 * i));   
    if (!MyWriteFileAndCheck(outFile, header, headerSize))   
      return PrintError(rs, "writing error");   

    if (res == SZ_OK)   
      res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable,   
        NULL, &g_Alloc, &g_Alloc);   
  }   
  LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);   
  return res;   
}   

int main2(int numArgs, const char *args[], char *rs)   
{   
  FILE *inFile = 0;   
  FILE *outFile = 0;   
  char c;   
  int res;   
  int encodeMode;   

  if (numArgs == 1)   
  {   
    PrintHelp(rs);   
    return 0;   
  }   

  if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)   
    return PrintUserError(rs);   

  c = args[1][0];   
  encodeMode = (c == 'e' || c == 'E');   
  if (!encodeMode && c != 'd' && c != 'D')   
    return PrintUserError(rs);   

  {   
    size_t t4 = sizeof(UInt32);   
    size_t t8 = sizeof(UInt64);   
    if (t4 != 4 || t8 != 8)   
      return PrintError(rs, "LZMA UTil needs correct UInt32 and UInt64");   
  }   

  inFile = fopen(args[2], "rb");   
  if (inFile == 0)   
    return PrintError(rs, "Can not open input file");   

  if (numArgs > 3)   
  {   
    outFile = fopen(args[3], "wb+");   
    if (outFile == 0)   
      return PrintError(rs, "Can not open output file");   
  }   
  else if (encodeMode)   
    PrintUserError(rs);   

  if (encodeMode)   
  {   
    res = Encode(inFile, outFile, rs);   
  }   
  else   
  {   
    res = Decode(inFile, outFile, rs);   
  }   

  if (outFile != 0)   
    fclose(outFile);   
  fclose(inFile);   

  if (res != SZ_OK)   
  {   
    if (res == SZ_ERROR_MEM)   
      return PrintError(rs, kCantAllocateMessage);   
    else if (res == SZ_ERROR_DATA)   
      return PrintError(rs, kDataErrorMessage);   
    else   
      return PrintErrorNumber(rs, res);   
  }   
  return 0;   
}   

int MY_CDECL main(int numArgs, const char *args[])   
{   
  char rs[800] = { 0 };   
  int res = main2(numArgs, args, rs);   
  printf(rs);   
  return res;   
}

您还可以在以下位置查看:

http://read.pudn.com/downloads151/sourcecode/zip/656407/7z460/C/LzmaUtil/LzmaUtil.c__.htm

http://read.pudn.com/downloads157/sourcecode/zip/698262/LZMA/LzmaUtil.c__.htm


16
只是一个复制粘贴SDK提供的示例源代码。它是如何工作的?这些调用在做什么?使用这段代码执行任务的最佳方式是什么?嗯。 - Captain Obvlious
这个例子没有正确地写入7zip文件头。我无法使用其他软件提取文件。例如,7z文件应该以“7z”字符串开头。 - truthseeker
这有助于展示如何对数据流进行LZMA压缩,而且它是SDK中少数展示至少一些东西的示例之一。而且这正是OP所请求的 - 应该标记为答案。 - St0fF

1

我最近发现了一个不错的例子,用C++编写。这个例子的原作者是GH用户Treeki,他发布了原始gist

// note: -D_7ZIP_ST is required when compiling on non-Windows platforms
// g++ -o lzma_sample -std=c++14 -D_7ZIP_ST lzma_sample.cpp LzmaDec.c LzmaEnc.c LzFind.c

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <memory>
#include "LzmaEnc.h"
#include "LzmaDec.h"

static void *_lzmaAlloc(ISzAllocPtr, size_t size) {
    return new uint8_t[size];
}
static void _lzmaFree(ISzAllocPtr, void *addr) {
    if (!addr)
        return;

    delete[] reinterpret_cast<uint8_t *>(addr);
}

static ISzAlloc _allocFuncs = {
    _lzmaAlloc, _lzmaFree
};



std::unique_ptr<uint8_t[]> lzmaCompress(const uint8_t *input, uint32_t inputSize, uint32_t *outputSize) {
    std::unique_ptr<uint8_t[]> result;

    // set up properties
    CLzmaEncProps props;
    LzmaEncProps_Init(&props);
    if (inputSize >= (1 << 20))
        props.dictSize = 1 << 20; // 1mb dictionary
    else
        props.dictSize = inputSize; // smaller dictionary = faster!
    props.fb = 40;

    // prepare space for the encoded properties
    SizeT propsSize = 5;
    uint8_t propsEncoded[5];

    // allocate some space for the compression output
    // this is way more than necessary in most cases...
    // but better safe than sorry
    //   (a smarter implementation would use a growing buffer,
    //    but this requires a bunch of fuckery that is out of
    ///   scope for this simple example)
    SizeT outputSize64 = inputSize * 1.5;
    if (outputSize64 < 1024)
        outputSize64 = 1024;
    auto output = std::make_unique<uint8_t[]>(outputSize64);

    int lzmaStatus = LzmaEncode(
        output.get(), &outputSize64, input, inputSize,
        &props, propsEncoded, &propsSize, 0,
        NULL,
        &_allocFuncs, &_allocFuncs);

    *outputSize = outputSize64 + 13;
    if (lzmaStatus == SZ_OK) {
        // tricky: we have to generate the LZMA header
        // 5 bytes properties + 8 byte uncompressed size
        result = std::make_unique<uint8_t[]>(outputSize64 + 13);
        uint8_t *resultData = result.get();

        memcpy(resultData, propsEncoded, 5);
        for (int i = 0; i < 8; i++)
            resultData[5 + i] = (inputSize >> (i * 8)) & 0xFF;
        memcpy(resultData + 13, output.get(), outputSize64);
    }

    return result;
}


std::unique_ptr<uint8_t[]> lzmaDecompress(const uint8_t *input, uint32_t inputSize, uint32_t *outputSize) {
    if (inputSize < 13)
        return NULL; // invalid header!

    // extract the size from the header
    UInt64 size = 0;
    for (int i = 0; i < 8; i++)
        size |= (input[5 + i] << (i * 8));

    if (size <= (256 * 1024 * 1024)) {
        auto blob = std::make_unique<uint8_t[]>(size);

        ELzmaStatus lzmaStatus;
        SizeT procOutSize = size, procInSize = inputSize - 13;
        int status = LzmaDecode(blob.get(), &procOutSize, &input[13], &procInSize, input, 5, LZMA_FINISH_END, &lzmaStatus, &_allocFuncs);

        if (status == SZ_OK && procOutSize == size) {
            *outputSize = size;
            return blob;
        }
    }

    return NULL;
}



void hexdump(const uint8_t *buf, int size) {
    int lines = (size + 15) / 16;
    for (int i = 0; i < lines; i++) {
        printf("%08x | ", i * 16);

        int lineMin = i * 16;
        int lineMax = lineMin + 16;
        int lineCappedMax = (lineMax > size) ? size : lineMax;

        for (int j = lineMin; j < lineCappedMax; j++)
            printf("%02x ", buf[j]);
        for (int j = lineCappedMax; j < lineMax; j++)
            printf("   ");

        printf("| ");

        for (int j = lineMin; j < lineCappedMax; j++) {
            if (buf[j] >= 32 && buf[j] <= 127)
                printf("%c", buf[j]);
            else
                printf(".");
        }
        printf("\n");
    }
}


void testIt(const uint8_t *input, int size) {
    printf("Test Input:\n");
    hexdump(input, size);

    uint32_t compressedSize;
    auto compressedBlob = lzmaCompress(input, size, &compressedSize);

    if (compressedBlob) {
        printf("Compressed:\n");
        hexdump(compressedBlob.get(), compressedSize);
    } else {
        printf("Nope, we screwed it\n");
        return;
    }

    // let's try decompressing it now
    uint32_t decompressedSize;
    auto decompressedBlob = lzmaDecompress(compressedBlob.get(), compressedSize, &decompressedSize);

    if (decompressedBlob) {
        printf("Decompressed:\n");
        hexdump(decompressedBlob.get(), decompressedSize);
    } else {
        printf("Nope, we screwed it (part 2)\n");
        return;
    }

    printf("----------\n");
}

void testIt(const char *string) {
    testIt((const uint8_t *)string, strlen(string));
}


int main(int argc, char **argv) {
    testIt("a");
    testIt("here is a cool string");
    testIt("here's something that should compress pretty well: abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef");

    return 0;
}

0

您可以参考这个文件来了解如何使用lzma2。

https://github.com/Tencent/libpag/blob/aab6391e455193c8ec5b8e2031b495b3fe77b034/test/framework/utils/LzmaUtil.cpp

/////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Tencent is pleased to support the open source community by making libpag available.
//
//  Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
//  except in compliance with the License. You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  unless required by applicable law or agreed to in writing, software distributed under the
//  license is distributed on an "as is" basis, without warranties or conditions of any kind,
//  either express or implied. see the license for the specific language governing permissions
//  and limitations under the license.
//
/////////////////////////////////////////////////////////////////////////////////////////////////

#include "LzmaUtil.h"
#include "test/framework/lzma/Lzma2DecMt.h"
#include "test/framework/lzma/Lzma2Enc.h"

namespace pag {
static void* LzmaAlloc(ISzAllocPtr, size_t size) {
  return new uint8_t[size];
}

static void LzmaFree(ISzAllocPtr, void* address) {
  if (!address) {
    return;
  }
  delete[] reinterpret_cast<uint8_t*>(address);
}

static ISzAlloc gAllocFuncs = {LzmaAlloc, LzmaFree};

class SequentialOutStream {
 public:
  virtual ~SequentialOutStream() = default;

  virtual bool write(const void* data, size_t size) = 0;
};

class SequentialInStream {
 public:
  virtual ~SequentialInStream() = default;

  virtual bool read(void* data, size_t size, size_t* processedSize) = 0;
};

struct CSeqInStreamWrap {
  ISeqInStream vt;
  std::unique_ptr<SequentialInStream> inStream;
};

struct CSeqOutStreamWrap {
  ISeqOutStream vt;
  std::unique_ptr<SequentialOutStream> outStream;
};

class BuffPtrInStream : public SequentialInStream {
 public:
  explicit BuffPtrInStream(const uint8_t* buffer, size_t bufferSize)
      : buffer(buffer), bufferSize(bufferSize) {
  }

  bool read(void* data, size_t size, size_t* processedSize) override {
    if (processedSize) {
      *processedSize = 0;
    }
    if (size == 0 || position >= bufferSize) {
      return true;
    }
    auto remain = bufferSize - position;
    if (remain > size) {
      remain = size;
    }
    memcpy(data, static_cast<const uint8_t*>(buffer) + position, remain);
    position += remain;
    if (processedSize) {
      *processedSize = remain;
    }
    return true;
  }

 private:
  const uint8_t* buffer = nullptr;
  size_t bufferSize = 0;
  size_t position = 0;
};

class VectorOutStream : public SequentialOutStream {
 public:
  explicit VectorOutStream(std::vector<uint8_t>* buffer) : buffer(buffer) {
  }

  bool write(const void* data, size_t size) override {
    auto oldSize = buffer->size();
    buffer->resize(oldSize + size);
    memcpy(&(*buffer)[oldSize], data, size);
    return true;
  }

 private:
  std::vector<uint8_t>* buffer;
};

class BuffPtrSeqOutStream : public SequentialOutStream {
 public:
  BuffPtrSeqOutStream(uint8_t* buffer, size_t size) : buffer(buffer), bufferSize(size) {
  }

  bool write(const void* data, size_t size) override {
    auto remain = bufferSize - position;
    if (remain > size) {
      remain = size;
    }
    if (remain != 0) {
      memcpy(buffer + position, data, remain);
      position += remain;
    }
    return remain != 0 || size == 0;
  }

 private:
  uint8_t* buffer = nullptr;
  size_t bufferSize = 0;
  size_t position = 0;
};

static const size_t kStreamStepSize = 1 << 31;

static SRes MyRead(const ISeqInStream* p, void* data, size_t* size) {
  CSeqInStreamWrap* wrap = CONTAINER_FROM_VTBL(p, CSeqInStreamWrap, vt);
  auto curSize = (*size < kStreamStepSize) ? *size : kStreamStepSize;
  if (!wrap->inStream->read(data, curSize, &curSize)) {
    return SZ_ERROR_READ;
  }
  *size = curSize;
  return SZ_OK;
}

static size_t MyWrite(const ISeqOutStream* p, const void* buf, size_t size) {
  auto* wrap = CONTAINER_FROM_VTBL(p, CSeqOutStreamWrap, vt);
  if (wrap->outStream->write(buf, size)) {
    return size;
  }
  return 0;
}

class Lzma2Encoder {
 public:
  Lzma2Encoder() {
    encoder = Lzma2Enc_Create(&gAllocFuncs, &gAllocFuncs);
  }

  ~Lzma2Encoder() {
    Lzma2Enc_Destroy(encoder);
  }

  std::shared_ptr<Data> code(const std::shared_ptr<Data>& inputData) {
    if (encoder == nullptr || inputData == nullptr || inputData->size() == 0) {
      return nullptr;
    }
    auto inputSize = inputData->size();
    CLzma2EncProps lzma2Props;
    Lzma2EncProps_Init(&lzma2Props);
    lzma2Props.lzmaProps.dictSize = inputSize;
    lzma2Props.lzmaProps.level = 9;
    lzma2Props.numTotalThreads = 4;
    Lzma2Enc_SetProps(encoder, &lzma2Props);
    std::vector<uint8_t> outBuf;
    outBuf.resize(1 + 8);
    outBuf[0] = Lzma2Enc_WriteProperties(encoder);
    for (int i = 0; i < 8; i++) {
      outBuf[1 + i] = static_cast<uint8_t>(inputSize >> (8 * i));
    }
    CSeqInStreamWrap inWrap = {};
    inWrap.vt.Read = MyRead;
    inWrap.inStream = std::make_unique<BuffPtrInStream>(
        static_cast<const uint8_t*>(inputData->data()), inputSize);
    CSeqOutStreamWrap outStream = {};
    outStream.vt.Write = MyWrite;
    outStream.outStream = std::make_unique<VectorOutStream>(&outBuf);
    auto status =
        Lzma2Enc_Encode2(encoder, &outStream.vt, nullptr, nullptr, &inWrap.vt, nullptr, 0, nullptr);
    if (status != SZ_OK) {
      return nullptr;
    }
    return Data::MakeWithCopy(&outBuf[0], outBuf.size());
  }

 private:
  CLzma2EncHandle encoder = nullptr;
};

std::shared_ptr<Data> LzmaUtil::Compress(const std::shared_ptr<Data>& pixelData) {
  Lzma2Encoder encoder;
  return encoder.code(pixelData);
}

class Lzma2Decoder {
 public:
  Lzma2Decoder() {
    decoder = Lzma2DecMt_Create(&gAllocFuncs, &gAllocFuncs);
  }

  ~Lzma2Decoder() {
    if (decoder) {
      Lzma2DecMt_Destroy(decoder);
    }
  }

  std::shared_ptr<Data> code(const std::shared_ptr<Data>& inputData) {
    if (decoder == nullptr || inputData == nullptr || inputData->size() == 0) {
      return nullptr;
    }
    auto input = static_cast<const uint8_t*>(inputData->data());
    auto inputSize = inputData->size() - 9;
    Byte prop = static_cast<const Byte*>(input)[0];

    CLzma2DecMtProps props;
    Lzma2DecMtProps_Init(&props);
    props.inBufSize_ST = inputSize;
    props.numThreads = 1;

    UInt64 outBufferSize = 0;
    for (int i = 0; i < 8; i++) {
      outBufferSize |= (input[1 + i] << (i * 8));
    }

    auto outBuffer = new uint8_t[outBufferSize];
    CSeqInStreamWrap inWrap = {};
    inWrap.vt.Read = MyRead;
    inWrap.inStream = std::make_unique<BuffPtrInStream>(input + 9, inputSize);
    CSeqOutStreamWrap outWrap = {};
    outWrap.vt.Write = MyWrite;
    outWrap.outStream = std::make_unique<BuffPtrSeqOutStream>(outBuffer, outBufferSize);
    UInt64 inProcessed = 0;
    int isMT = false;
    auto res = Lzma2DecMt_Decode(decoder, prop, &props, &outWrap.vt, &outBufferSize, 1, &inWrap.vt,
                                 &inProcessed, &isMT, nullptr);
    if (res == SZ_OK && inputSize == inProcessed) {
      return Data::MakeAdopted(outBuffer, outBufferSize, Data::DeleteProc);
    }
    delete[] outBuffer;
    return nullptr;
  }

 private:
  CLzma2DecMtHandle decoder = nullptr;
};

std::shared_ptr<Data> LzmaUtil::Decompress(const std::shared_ptr<Data>& data) {
  Lzma2Decoder decoder;
  return decoder.code(data);
}
}  // namespace pag

虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅链接的答案可能会失效。- 来自审查 - Chris
@Chris 好的,我已经更新了。谢谢你的提醒。 - 吕鹏伟

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接