为 7-Zip 写一个存档格式插件 (6):7-Zip 的插件机制

插件机制

上一篇文中,咱们已经实现出了本身的存档包格式处理类,但估计你也像我同样,不想直接发布集成该格式的 7-Zip 安装包,毕竟用户电脑上可能已经装了 7-Zip,再装一个就重复了。再加上若是这样发布的话,咱们就要跟随 7z 官方的更新,每次 7z 更新,咱们也要更新本身的代码,这多麻烦。git

有没有一劳永逸的方法呢?实际上是有的,就是编译为外部插件。7-Zip 用官方安装包就行,只要加载咱们的插件就能增长新的格式支持。插件编译出来后,基本上是能够一直用下去的,官方接口应该不会随意改动。github

事实上,官方安装包中的 7z.exe7zFM.exe 就是基于 7z.dll 这个外部插件的,不信你能够把 7z.dll 文件删掉,会发现 7z 已经不支持任何格式,彻底就是一个空壳程序。app

虽然官方文档中什么都没有说,但从源码中能够知道,7z 支持 2 种类型的插件:Codecs 和 Formats。继续分析源码,会发现这两种插件其实没有任何差异,甚至代码中对它们的加载方式都是一致的,只不过保存的目录不一样。函数

注意:下面说的全部内容,官方都没有写入文档,彻底是我分析源码得出的结论,将来随时可能被修改oop

插件保存位置

默认状况下,7z 会从下面 3 个位置加载插件:编码

  • <安装目录>/7z.dll
  • <安装目录>/Codecs/*.dll
  • <安装目录>/Formats/*.dll

第一个位置已经被官方占用了,咱们能够把本身的插件放入后面二者中的任意一个。除了目录名不一样,插件的工做方式没有任何区别。spa

插件接口

上面说了,官方安装包中的 7z.dll 就是一个插件,它的项目目录在 CPP/7zip/Bundles/Format7zF,咱们能够从这个项目入手,找到插件接口。插件

打开项目,会发现接口其实很好找,官方已经建立了分类目录,就是项目中的 Spec 目录。code

clipboard.png

注意,这里的 Archive2.defDllExports2.cpp,文件名中都带个 2,其实还有不带 2 的这俩文件,它们的区别是:带后缀 2 的支持导出编解码器,而不带后缀的只能导出存档包格式处理器。orm

咱们并无实现编解码器,因此选择不带后缀的这组就好了,同时删去 CodecExports.cpp

因为有编码洁癖,我选择从头开始建立项目。

打开 VS,新建一个 dll 空项目,把上面说的 Archive.defArchiveExports.cppDllExports.cpp 加入项目。其中 DllExports.cpp 文件中已经实现了 DllMain 函数,咱们不用重复实现。

而后。。编译一下?哈哈,确定编译不过,哪有这么简单。

经过几回尝试,我把依赖关系理清了,把下面这些文件都加入项目:

clipboard.png

好了,这就是插件项目的最小依赖关系。

再编译一下?哈哈,不出意外仍是不行的,须要改一改 stdafx.h,把里面已有的内容删掉,写入这些内容:

#pragma once

// 按你项目的实际放置位置,修改这里的路径
#include "../../../Common/Common.h"

如今编译就 OK 了。

把编译出的 dll 放入上面说的插件目录中,从新打开 7z,应该就能用了。

经过 7z i 命令,能够看到:

Libs:
 0  D:\scoop\home\apps\7zip\current\7z.dll
 1  D:\scoop\home\apps\7zip\current\Formats\FormatZzz_x64.dll

Formats:
 ...
 1               Zzz      zzz

咱们的插件已经被加载进来了,支持的格式里也有了咱们添加的格式。

最后,相关源码在 https://github.com/wzv5/7z-formatzzz

再说点不相关的,7-Zip 的开源协议是 LGPL,使用请谨慎。我不知道若是实现为外部插件,而且把上面说的那些依赖文件所有本身重写,也就是本身实现这套插件接口,还受不受 LGPL 协议限制,使用私有 API 接口算不算侵权呢?你还记得甲骨文是怎么告 Google 的 Android 侵权的么?可是微软和 Wine、Mono 又能和平共处,因此这是个迷。

相关文章
相关标签/搜索