Dll中匯出類--Delphi實戰之一 (轉)
Dll中匯出類--實戰之一:namespace prefix = o ns = "urn:schemas--com::office" />
作者: Musicwind®
建立時間: 2001-11-01
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
歷史:No.1
更新時間:2001-11-01 20:09
更新人員:Musicwind®
更新備註:初稿完成。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
摘要:
本文討論的是如何在Dll中匯出類——基於某個特定的抽象類的許多子類。這種技術運用了多型的思想,使得我們得到類似於的效果。
預期讀者:
瞭解多型的概念;瞭解元類的概念。
技術難度:
6/10。
從Dll中匯出類,想必大家首先想到的是使用bpl包。這種方式有一個不好,那就是使用者必須清楚這個包中含有那些類,也就是說必須知道類的名字——這在一定意義上是個限制,試想一種情況,使用者定義了一個底層的抽象類(abstract class),然後在此基礎上定義了許多應用類(concrete class),那麼,對於使用者來說,他希望在不知道具體有哪些類的情況下能使用這些類——這麼說似乎有些玄,但實際情況確實如此,因為定義抽象類的時候並不能預料到以後會有多少個具體類——那麼這樣的需求,要靠什麼樣的技術來實現呢?
其實實現的技術的難度並不大——作者在此將自己實踐的獻給大家,算作拋磚引玉,希望能看到其他更好的方法!
以下先介紹該方法涉及的一些基礎知識,然後用一個例子來說明具體的實現。
一、基本概念
元類(meta class),也叫類引用型別(class-reference type),可以看成是一種類的型別,以該型別宣告的變數的值代表一個類。比如:
type
TClass = Class of T;
這樣就宣告瞭一個元類的型別。然後可以有這樣的變數宣告:
Var
AClass: TClass;
那麼,就可以有這樣的用法:
AClass := TObject;
或者:
AClass := TButton;
或者:
AClass := TForm;
等等。
因為TClass是一個TObject型別的元類,而TButton,TForm等都是自TObject派生而來,因而TButton和TForm這樣的值對於AClass都是可接受的。
然後,我們就可以運用多型的思想,靈活運用AClass這個類變數了。而這一點也正是下文具體實現的基礎知識。
二、具體實現
第一步,建立一個抽象類:
我們使用這樣一個簡單的宣告,該抽象類只提供了一種抽象方法,但並不影響我們描述問題:
TMyBaseFo= Class(TForm)
protected
function GetTitle: pchar; virtual; abstract;
end;
MyBaseFormClass = Class of TMyBaseForm;
暫不探討這麼一個抽象類提供了多少可供實用的方法和介面,因為我們要討論的是一種技術上的可行性。假設作者定義此介面的初衷只是希望獲得任意多變化的Title,而具體GetTitle的返回值是什麼需要靠子類來實現。並且,作者還希望子類的程式碼放在Dll中實現,與主分離——這樣的方式很有些外掛的味道,或許還能實現Plug&Play的某些特性——是不是挺吸引人啊?那麼,下一不應該怎麼做呢?
首先主程式和Dll程式應當將上述宣告的單元包含進來,然後,主程式負責實現一個——動態載入Dll,動態載入類;而Dll負責實現子類。
先說Dll吧,Dll應當做什麼工作?
第二步,Dll中匯出子類:
我們設計了以下兩個匯出:
1. function GetClasunt: integer; stdcall;
告訴者,本Dll中共有幾個子類;
2.function GetClassTypeByIndex(const iIndex: integer;
var ClassType: MyBaseFormClass): Worool; stdcall;
以方式獲得具體的子類。注意,此處的ClassType的型別是MyBaseFormClass,這表明,它的值將是一個確定的自TMyBaseForm繼承而來的類。
以下是它們可能的一種實現:
function GetClassCount: integer;
begin
result := 3; //表明本Dll中匯出了3個類
end;
function GetClassTypeByIndex(const iIndex: integer;
var ClassType: MyBaseFormClass): Bool;
begin
result := True;
case iIndex of
0: ClassType := TFrmTest1;
1: ClassType := TFrmTest2;
2: ClassType := TFrmTest3;
else
result := False;
end;
end;
當然,在該單元的Use列表中應當將TFrmTest1、TFrmTest2以及TFrmTest3所在的單元包含進來。而TFrmTest1的實現可以象這樣:
TFrmTest1 = Class(TMyBaseForm)
protected
function GetTitle: PChar; overr;
end;
function TFrmTest1.GetTitle: Pchar;
begin
result := ‘Hello from TFrmTest1’;
end;
末了,別忘了將GetClassCount和GetClassByIndex加到Exports列表中。然後,Build該Dll工程的時候,請將Project option-package 中的”使用執行包use runtime package”打勾。至於具體的原因後面講。
至此,Dll方面的工作告一段落。
第三步,主程式驅動引擎的實現:
這一步相對來說容易些——無非是動態載入Dll,然後呼叫GetClassCount函式,接著呼叫GetClassByIndex。關鍵的程式碼:
Var AClass: TMyBaseClass;
AForm: TMyBaseForm;
I, iCount: integer;
blResult: Boolean;
begin
//略去載入動態庫的部分,假定FPGetClassProc指向GetClassCount函式,FPGetClassByIndexProc指向GetClassByIndex,則:
iCount := FPGetClassProc;
for I := 0 to iCount – 1 do
begin
AClass := FPGetClassByIndex(I, blResult);
if blResult then
begin
AForm := AClass.Create(Application);
AForm.Caption := AForm.GetTitle;
AForm.Show;
end;
end;
//…
end;
注意一點,和Dll相似,建立輸出的時候,也需要選擇使用執行時間包。這是因為,如果不使用執行時間包,將導致相同的類在中有多個副本,因而對它們使用Is運算子的將返回False的結果。
Musicwind®@HangZhou.Zhejiang.China
2001-11-01
/develop/my_article.?author=Musicwind">更多文章
[文終]
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991416/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C++關於DLL匯出模板類和模板函式C++函式
- delphi cxgrid匯出excel去除貨幣符號Excel符號
- 從Delphi到Lazarus——Delphi轉換器
- QT5.12 匯出exe依賴的dllQT
- Delphi TDictionary字典類
- delphi 判斷類是否實現介面,獲取類實現的介面
- kubebuilder實戰之一:準備工作kubebuilder實戰之一:準備工作UI
- OpenFaaS實戰之一:部署
- Windows提權實戰————4、DLL注入Windows
- Windows環境下,動態連結庫(DLL)的“匯入”與“匯出”概念Windows
- 【實戰】通過 JS 將 HTML 匯出為 PDF 文件JSHTML
- java設定熱鍵(C++實現dll匯入)JavaC++
- Vue框架下實現匯入匯出Excel、匯出PDFVue框架Excel
- javascript中的匯出和匯入實現模組化管理JavaScript
- netty實戰之一 認識nettyNetty
- Flink的sink實戰之一:初探
- Spring Cloud Gateway實戰之一:初探SpringCloudGateway
- 匯出類介面如何斷言
- java實現Excel定製匯出(基於POI的工具類)JavaExcel
- Excel匯出實列Excel
- Vue + Element 實現匯入匯出ExcelVueExcel
- HExcel,一個簡單通用的匯入匯出Excel工具類Excel
- 二進位制陣列實戰 – 純前端匯出Excel檔案陣列前端Excel
- 二進位制陣列實戰 - 純前端匯出Excel檔案陣列前端Excel
- Mvc 5中匯出ExcelMVCExcel
- 前端實現Excel匯入和匯出功能前端Excel
- js匯入匯出總結與實踐JS
- 【最佳實踐】MongoDB匯出匯入資料MongoDB
- 使用xlsx file-saver exceljs實現瀏覽器中Excel匯入匯出ExcelJS瀏覽器
- 關於java中Excel的匯入匯出JavaExcel
- strimzi實戰之一:簡介和準備
- Kurento實戰之一:KMS部署和體驗
- DL4J實戰之一:準備
- client-go實戰之一:準備工作clientGo
- MyBatis初級實戰之一:Spring Boot整合MyBatisSpring Boot
- SpringCloud微服務實戰——搭建企業級開發框架(三十):整合EasyExcel實現資料表格匯入匯出功能SpringGCCloud微服務框架Excel
- spring boot + easypoi快速實現excel匯入匯出Spring BootExcel
- Laravel Maatwebsite-Excel 3.1 實現匯出匯入LaravelWebExcel
- python 小指令碼 (實現 elasticsearch 匯出匯入)Python指令碼Elasticsearch