舉個例子好了
二
IMyInterface = interface(IInterface) //說明(
[
function GetName(const str: String): String; stdcall;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; //說明(
function _AddRef: Integer; stdcall; //使接口引用數加
function _Release: Integer; stdcall;//使接口引用數減
end;
說明(
說明(
說明(
接口服務是由類來實現的
TIntfClass = class(TObject
private
FCounter: Integer;
FRefCount: Integer;
public
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
end;
a
var aIntf: IMyInterface;
begin
aObj := TIntfClass
try
aIntf := (IMyInterface(aObj);
b
c
d
使用as操作符必須符合下面條件
在Delphi
TIntfClass = class(TInterfacedObject
因為Delphi會自行檢查接口如果在使用後沒有釋放而在生成的程序裡加上釋放代碼
var
i: Integer;
aObj: TIntfClass;
aIntf
begin
aObj := TIntfclass
try
aIntf := aObj;
aIntf
finally
aIntf := nil;
FreeAndNil(aObj);
end;
上面的代碼執行的話會產生存取違規錯誤
nil時已釋放了該對象
function TIntfClass
begin
Result := InterlockedDecrement(FRefCount);
end;
分為兩種
IImplInterface = interface(IInterface)
function ConvertToUSD(const iNTD: Integer): Double;
function ConvertToRMB(const iNTD: Integer): Double;
end;
接著有一個類實現了該接口
TImplClass = class(TObject
private
FRefCount: Integer;
public
function ConvertToUSD(const iNTD: Integer): Double;
end;
implementation
function TImplClass
begin
if GetInterface(IID
Result :=
else
Result := E_NOINTERFACE;
end;
function TImplClass
begin
Result := InterlockedDecrement(FRefCount);
if Result =
Destroy;
end;
現在有另外一個類TIntfServiceClass要實現IImplInterface接口
TIntfServiceClass = class(TObject
private
FImplService: IImplInterface;
//FSrvObj: TImplClass; //如果是用類對象委托的話
public
Constructor Create; overload;
Destructor Destroy; override;
Constructor Create(aClass: TClass); overload;
property MyService: IImplInterface read FImplService implements IImplInterface;
// property MyService: TImplClass read FSrvObj implements IImplInterface; //如果是用對象委托的話
end;
實現如下
constructor TIntfServiceClass
begin
FImplService := TImplClass
end;
constructor TIntfServiceclass
var
instance: TImplClass;
begin
instance := TImplClass(aClass
FImplService := instance
end;
destructor TIntfServiceClass
begin
FImplService := nil; //遵照TImplClass使用引用計數來控制對象生命周期
inherited;
end;
Delphi中在VMT
相關函數
GetInterfaceCount; //獲取接口數量
GetInterfaceTable; //獲取接口表格
相關結構
TInterfaceEntry = packed record
IID: TGUID;
VTable: Pointer;
IOffset: Integer;
ImplGetter: Integer;
end;
PInterfaceTable = ^TInterfaceTable;
TInterfaceTable = packed record
EntryCount: Integer;
Entries: array[
end;
Self是指向VMT指針的指針
aPtr := PPointer(Integeer((Pointer(Self))^) + vmtIntfTable)^;
只要在聲明中使用M+/M
{$M+}
iInvokable = interface(IInterface)
{$M
接口的RTTI信息由TIntfMetaData記錄結構定義
TIntfMetaData = record
name: String; //接口名稱
UnitName: String; //接口聲明的程序單元名稱
MDA: TIntfMethEntryArray; //儲存接口中方法信息的動態數組
IID: TGUID; //接口的GUID值
Info: PTypeInfo; //描述接口信息的指針
AncInfo: PTypeInfo; //描述父代信息的指針
NumAnc: Integer; //此接口繼承自父代接口的方法數目
end;
TIntfMethEntryArray的定義如下
type
TCallConv = (ccReg
TIntfMethEntry = record
Name: String; //方法名稱
CC: TCallConv; //調用慣例
Pos: Integer; //方法在接口中的位置
ParamCount: Integer; //方法的參數數目
ResultInfo: PTypeInfo; //描述方法回傳類型的信息指針
SelfInfo: PTypeInfo; //描述方法本身的信息指針
Params: TIntfParamEntryArray; //描述參數信息的動態數組
HasRTTI: Boolean; //這個方法是否擁有RTTI信息的布爾值
end;
TIntfMethEntryArray = array of TIntfMethEntry;
參數信息TIntfParamEntry定義
TIntfParamEntry = record
Flags: TParamFlags;
Name: String;
Info: PTypeInfo;
end;
TTypeInfo = record
Kind: TTypeKind; //數據類型
Name: ShortString; //類型信息的字符串格式
end;
From:http://tw.wingwit.com/Article/program/Delphi/201311/24851.html