我們的插件外殼程序與普通應(yīng)用程序之間的唯一不同就在于工程源文件中出現(xiàn)在uses子句中的Sharemem單元和加載插件文件的代碼。任何在自身與子DLL之間傳遞字符串參數(shù)的應(yīng)用? 都需要Sharemem單元,它是DelphiMM.dll(Delphi提供該文件)的接口。要測試這個(gè)外殼,需要將DelphiMM.dll文件從Delphi/Bin目錄復(fù)制到path環(huán)境變量所包含的路徑或者應(yīng)用程序所在目錄中。發(fā)布最終版本時(shí)也需要同時(shí)分發(fā)該文件。 插件通過LoadPlugins過程載入到這個(gè)測試外殼中,這個(gè)過程在主窗口的FormCreate事件中調(diào)用,見圖2。該過程使用FindFirst和FindNext函數(shù)在應(yīng)用程序所在目錄中查找插件文件。找到一個(gè)文件以后,就使用圖3所示的LoadPlugins過程將其載入。 { 在應(yīng)用程序目錄下查找插件文件 } PRocedure TfrmMain.LoadPlugins; var sr: TSearchRec; path: string; Found: Integer; begin path := ExtractFilePath(application.Exename); try Found := FindFirst(path + cPLUGIN_MASK, 0, sr); while Found = 0 do begin LoadPlugin(sr); Found := FindNext(sr); end; finally FindClose(sr); end; end;
{ 加載指定的插件 DLL. } procedure TfrmMain.LoadPlugin(sr: TSearchRec); var Description: string; LibHandle: Integer; DescribeProc: TPluginDescribe; begin LibHandle := LoadLibrary(Pchar(sr.Name)); if LibHandle $#@60;$#@62; 0 then begin DescribeProc := GetProcAddress(LibHandle, cPLUGIN_DESCRIBE); if Assigned(DescribeProc) then
begin DescribeProc(Description); memPlugins.Lines.Add(Description); end else begin MessageDlg(’File "’ + sr.Name +’" is not a valid plug-in.’, mtInformation, [mbOK], 0); end; end else MessageDlg(’An error occurred loading the plug-in "’ + sr.Name + ’".’, mtError, [mbOK], 0); end;
我們已經(jīng)創(chuàng)建好了父應(yīng)用程序,現(xiàn)在該輪到創(chuàng)建我們希望加載的插件了。插件文件是一個(gè)標(biāo)準(zhǔn)的Delphi DLL,所以我們從Delphi IDE中創(chuàng)建一個(gè)新DLL工程,保存它。由于導(dǎo)出的插件函數(shù)將用到字符串參數(shù),所以要在工程的uses子句中把Sharemen單元放在最前面。圖4列出的就是我們這個(gè)簡單插件的工程源文件。 uses Sharemem, SysUtils, Classes, main in ’main.pas’;
{$E plg.}
eXPorts DescribePlugin;
begin
end.
雖然插件是一個(gè)DLL文件,但是沒有必要一定要給它一個(gè).DLL的擴(kuò)展名。實(shí)際上,一個(gè)原因就足以讓我們有理由改變擴(kuò)展名:當(dāng)父應(yīng)用程序?qū)ふ乙虞d的文件時(shí),新的擴(kuò)展名可以作為特定的文件掩模。通過使用別的擴(kuò)展名(我們的例子使用了*.plg),你可以在一定程度上確信應(yīng)用程序只會(huì)載入相應(yīng)的文件。編譯指示字$X可以實(shí)現(xiàn)這個(gè)改變,也可以通過Project Options對(duì)話框的Application頁來設(shè)置擴(kuò)展名。 第一個(gè)例子插件的代碼是很簡單的。圖5顯示了包含在一個(gè)新單元中的代碼。注重,DescribePlugin原型與外殼應(yīng)用程序中的TpluginDescribe類型相一致,使用附加的export保留字指定該過程將被導(dǎo)出。被導(dǎo)出的過程名稱也將會(huì)出現(xiàn)在主工程源代碼的exports段中(在圖4中列出)。 unit main;