我原本并不想单独发以下JCL的方法,可是想到很多人可能还是不知道的。另外,从我博客的回复上看,很多人也愿意去了解一下,特此贴出JCL中的代码。
// === Interface information ==================================================
function GetImplementorOfInterface( const I: IInterface): TObject;
... { TODO -cDOC : Original code by Hallvard Vassbotn }
... { TODO -cTesting : Check the implemetation for any further version of compiler }
const
AddByte = $ 04244483 ; // opcode for ADD DWORD PTR [ESP+4], Shortint
AddLong = $ 04244481 ; // opcode for ADD DWORD PTR [ESP+4], Longint
type
PAdjustSelfThunk = ^ TAdjustSelfThunk;
TAdjustSelfThunk = packed record
case AddInstruction: Longint of
AddByte: (AdjustmentByte: ShortInt);
AddLong: (AdjustmentLong: Longint);
end;
PInterfaceMT = ^ TInterfaceMT;
TInterfaceMT = packed record
QueryInterfaceThunk: PAdjustSelfThunk;
end;
TInterfaceRef = ^ PInterfaceMT;
var
QueryInterfaceThunk: PAdjustSelfThunk;
begin
try
Result : = Pointer(I);
if Assigned(Result) then
begin
QueryInterfaceThunk : = TInterfaceRef(I) ^ .QueryInterfaceThunk;
case QueryInterfaceThunk.AddInstruction of
AddByte:
Inc(PChar(Result), QueryInterfaceThunk.AdjustmentByte);
AddLong:
Inc(PChar(Result), QueryInterfaceThunk.AdjustmentLong);
else
Result : = nil;
end;
end;
except
Result : = nil;
end;
end;
注释:这段代码出自JCL代码中JclSysUtils单元中。
提示:读这段代码,要明白一个道理,在代码执行过程中,接口和对象指针的偏移是硬编码的在汇编中的。转换的过程,就是解析这段汇编的过程。