爲 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 又能和平共處,因此這是個迷。

相關文章
相關標籤/搜索