源码下载地址:https://www.7-zip.org/download.html
下载后解压,然后使用Visual Studio 2008 SP1(一定要打SP1补丁,不然后面编译会很麻烦,各种报错,然后查看解决办法,也许最终还是回到打SP1补丁……) 打开%7z_source%\CPP\7zip\Bundles\Format7zF\Format7z.dsw,会有如下提示,选择标记的那个:
然后快捷键Alt+F7打开工程属性窗口,修改一下输出路径(也可以不修改),F7编译,报错fatal error LNK1107: invalid or corrupt file: cannot read at 0x26D,修改如下两个文件的属性配置:
去掉Command Line 中的-omf(两个文件都是如此) ,然后rebuild(build还会报上面的错误,不懂的可以查查rebuild和build的区别)。
以上都不是关键,只是为了方便调试罢了。下面开始分析源码,我打算先从%7z_source%\C里面的文件开始(因为这里面是其他类的基础),下面介绍7zTypes.h里面的内容。
#ifndef EXTERN_C_BEGIN
#ifdef __cplusplus
#define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END }
#else
#define EXTERN_C_BEGIN
#define EXTERN_C_END
#endif
#endif
这段对宏EXTERN_C_BEGIN的定义,就不多加解释了,关于extern “C”的作用,参见extern “C”的作用详解
和C和C++混合编译。
#define SZ_OK 0
#define SZ_ERROR_DATA 1
#define SZ_ERROR_MEM 2
#define SZ_ERROR_CRC 3
#define SZ_ERROR_UNSUPPORTED 4
#define SZ_ERROR_PARAM 5
#define SZ_ERROR_INPUT_EOF 6
#define SZ_ERROR_OUTPUT_EOF 7
#define SZ_ERROR_READ 8
#define SZ_ERROR_WRITE 9
#define SZ_ERROR_PROGRESS 10
#define SZ_ERROR_FAIL 11
#define SZ_ERROR_THREAD 12
#define SZ_ERROR_ARCHIVE 16
#define SZ_ERROR_NO_ARCHIVE 17
这组宏是错误码,SZ_OK是执行成功,其他见名知意(具体为什么取这些值,是作者喜好)。
typedef int SRes;
#ifdef _WIN32
typedef unsigned WRes;
#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x)
#else
typedef int WRes;
#define MY__FACILITY_WIN32 7
#define MY__FACILITY__WRes MY__FACILITY_WIN32
#define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000)))
#endif
以上自定义了一种数据类型SRes,还有根据不同编译配置的数据类型WRes及宏函数MY_SRes_HRESULT_FROM_WRes(x)(我查看过,HRESULT_FROM_WIN32(x)定义在winerror.h中,#else分支的实现和HRESULT_FROM_WIN32(x)实际走的分支是一样的,估计作者是想32位和非32位的宏函数MY_SRes_HRESULT_FROM_WRes(x)实现保持一致吧,而且7zTypes.h中的许多内容摘自lzma918中Types.h)。7zTypes.h中还有其他类似的自定义类型和宏函数,就不一一介绍了。
/* The following interfaces use first parameter as pointer to structure */
typedef struct IByteIn IByteIn;
struct IByteIn
{
Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */
};
#define IByteIn_Read(p) (p)->Read(p)
typedef struct IByteOut IByteOut;
struct IByteOut
{
void (*Write)(const IByteOut *p, Byte b);
};
#define IByteOut_Write(p, b) (p)->Write(p, b)
从作者的注释中可以看出,这两个函数读写一个字节(函数指针,具体实例化在后期的调用中)。
typedef struct ISeqInStream ISeqInStream;
struct ISeqInStream
{
SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) < input(*size)) is allowed */
};
#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size)
读数据流,read()的后两个参数buf 和size既是输入参数又是输出参数,buf存放读出的数据,size作为输入,是期望读到的大小,作为输出,是实际读到的大小(函数指针,具体实例化在后期的调用中)。
typedef struct ISeqOutStream ISeqOutStream;
struct ISeqOutStream
{
size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size);
/* Returns: result - the number of actually written bytes.
(result < size) means error */
};
#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size)
写数据流(类似上面的read函数,具体实例化在后期的调用中)。
typedef enum
{
SZ_SEEK_SET = 0,
SZ_SEEK_CUR = 1,
SZ_SEEK_END = 2
} ESzSeek;
typedef struct ISeekInStream ISeekInStream;
struct ISeekInStream
{
SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin);
};
#define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size)
#define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
typedef struct ILookInStream ILookInStream;
struct ILookInStream
{
SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) > input(*size)) is not allowed
(output(*size) < input(*size)) is allowed */
SRes (*Skip)(const ILookInStream *p, size_t offset);
/* offset must be <= output(*size) of Look */
SRes (*Read)(const ILookInStream *p, void *buf, size_t *size);
/* reads directly (without buffer). It's same as ISeqInStream::Read */
SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin);
};
#define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size)
#define ILookInStream_Skip(p, offset) (p)->Skip(p, offset)
#define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size)
#define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
类似于文件的操作,只是此处对象是数据流而已。
typedef struct ICompressProgress ICompressProgress;
struct ICompressProgress
{
SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize);
/* Returns: result. (result != SZ_OK) means break.
Value (UInt64)(Int64)-1 for size means unknown value. */
};
#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize)
函数指针,用来处理压缩进度。
其他还有一些结构体的定义和函数声明,就不再介绍(详情可看7zTypes.h)。