Delphi中判断类是否支持某个GUID的源码,看起来很简单的代码,本人十分困扰 ( 积分: 100 )

  • 主题发起人 主题发起人 wodesnake
  • 开始时间 开始时间
W

wodesnake

Unregistered / Unconfirmed
GUEST, unregistred user!
个人在看DELPHI中关于从类中获取接口中的源码,下面是寻找接口的代码<br>class&nbsp;function&nbsp;TObject.GetInterfaceEntry(const&nbsp;IID:&nbsp;TGUID):&nbsp;PInterfaceEntry;<br>{$IFDEF&nbsp;PUREPASCAL}<br>var<br>&nbsp;&nbsp;ClassPtr:&nbsp;TClass;<br>&nbsp;&nbsp;IntfTable:&nbsp;PInterfaceTable;<br>&nbsp;&nbsp;I:&nbsp;Integer;<br>begin<br>&nbsp;&nbsp;ClassPtr&nbsp;:=&nbsp;Self;<br>&nbsp;&nbsp;while&nbsp;ClassPtr&nbsp;&lt;&gt;&nbsp;nil&nbsp;do<br>&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;IntfTable&nbsp;:=&nbsp;ClassPtr.GetInterfaceTable;<br>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;IntfTable&nbsp;&lt;&gt;&nbsp;nil&nbsp;then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;I&nbsp;:=&nbsp;0&nbsp;to&nbsp;IntfTable.EntryCount-1&nbsp;do<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Result&nbsp;:=&nbsp;@IntfTable.Entries;<br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;Result^.IID&nbsp;=&nbsp;IID&nbsp;then&nbsp;Exit;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(Int64(Result^.IID.D1)&nbsp;=&nbsp;Int64(IID.D1))&nbsp;and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Int64(Result^.IID.D4)&nbsp;=&nbsp;Int64(IID.D4))&nbsp;then&nbsp;Exit;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;<br>&nbsp;&nbsp;&nbsp;&nbsp;ClassPtr&nbsp;:=&nbsp;ClassPtr.ClassParent;<br>&nbsp;&nbsp;end;<br>&nbsp;&nbsp;Result&nbsp;:=&nbsp;nil;<br>end;<br>{$ELSE}<br>主要搞不懂这一段,BORLAND为什么把下面一句判断注释掉,而使用第二种判断方式<br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;Result^.IID&nbsp;=&nbsp;IID&nbsp;then&nbsp;Exit;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(Int64(Result^.IID.D1)&nbsp;=&nbsp;Int64(IID.D1))&nbsp;and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Int64(Result^.IID.D4)&nbsp;=&nbsp;Int64(IID.D4))&nbsp;then&nbsp;Exit;<br>GUID比较应该比较16个字节,对于第二种比较方式怎么看起来也没有比较16个字节,<br>(Int64(Result^.IID.D1)&nbsp;=&nbsp;Int64(IID.D1))&nbsp;,&nbsp;GUID中的D1都只占4个字节,经过类型转换<br>也只是值转换成64位(8个字节)的整形,但并没有从D1开始取8个字节进行比较。那么D2,D3共4个字节都没有比较,这个怎么能判断两个GUID相等了?<br><br>&nbsp;var<br>&nbsp;&nbsp;&nbsp;&nbsp;b:&nbsp;Byte;<br>&nbsp;&nbsp;&nbsp;&nbsp;I:&nbsp;Integer;<br>&nbsp;&nbsp;b&nbsp;:=&nbsp;50;<br>&nbsp;&nbsp;I&nbsp;:=&nbsp;Integer(b);&nbsp;//像这种类似的转换,只是把b的值50赋给I罢了,而不是从b单元开始的4个字节的值赋给I。<br>同理&nbsp;(Int64(Result^.IID.D1)&nbsp;=&nbsp;Int64(IID.D1))&nbsp;只比较4个字节,所以D2,D3共4个字节并没有参与比较,难道真的只能理解两个GUID的D2,D3出现相同的概率相当小
 
请看清TGUID的定义:<br>&nbsp;&nbsp;TGUID&nbsp;=&nbsp;packed&nbsp;record<br>&nbsp;&nbsp;&nbsp;&nbsp;D1:&nbsp;LongWord;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//4字节,32位<br>&nbsp;&nbsp;&nbsp;&nbsp;D2:&nbsp;Word;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//2字节,16位<br>&nbsp;&nbsp;&nbsp;&nbsp;D3:&nbsp;Word;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//2字节,16位<br>&nbsp;&nbsp;&nbsp;&nbsp;D4:&nbsp;array[0..7]&nbsp;of&nbsp;Byte;&nbsp;//8字节,64位<br>&nbsp;&nbsp;end;<br>故&nbsp;D1+D2+D3=8字节,64位,即一个Int64,<br>&nbsp;&nbsp;&nbsp;D4=8字节,64位,即一个Int64.
 
这个我看清楚了,不知道dreamisx是怎么理解类型转换的<br>我想问Int64(变量),会从变量开始的单元起取8个字节吗?<br>对于类型转换&nbsp;大类型转换成小类型值可能会丢失,但小类型转大类型值是不变的,<br>也就是说Int64(IID.D1)=D1<br><br>测试代码<br><br>procedure&nbsp;TForm1.Button1Click(Sender:&nbsp;TObject);<br>var<br>&nbsp;&nbsp;T:&nbsp;TGUID;<br>begin<br>&nbsp;&nbsp;T.D1&nbsp;:=&nbsp;1;<br>&nbsp;&nbsp;T.D2&nbsp;:=&nbsp;2;<br>&nbsp;&nbsp;t.D3&nbsp;:=&nbsp;3;<br>&nbsp;&nbsp;T.D4[0]&nbsp;:=&nbsp;4;<br>&nbsp;&nbsp;showmessage(inttostr(Int64(T.D1)));<br>end;<br><br>按你所说的int64(T.D1)会把D2,D3都取出来,共取8个字节,但上面的测试代码输出值为1,而并非由D1,D2,D3三个组成的值
 
值得关注,<br>感觉应该把<br>(Int64(Result^.IID.D1)<br>写成(PInt64(@Result^.IID.D1)^<br>才合理。
 
而且无论是看GetInterfaceEntry在VCL中的汇编代码,还是写个例子调用GetInterfaceEntry看它反汇编的代码,都是以四字节为单位挨个比较的。这就更和<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(Int64(Result^.IID.D1)&nbsp;=&nbsp;Int64(IID.D1))&nbsp;and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Int64(Result^.IID.D4)&nbsp;=&nbsp;Int64(IID.D4))&nbsp;then&nbsp;Exit;<br>不一致了。
 
Pascal&nbsp;应该是写错了。运行时库用的是ASM,这段Pascal代码下面的ASM里可以看出,比较过程对全部16个字节都进行了比较。
 
是的,汇编代码的确是比较了16个字节,看来纯PASCAL的是错了,谢谢‘小雨哥’同时也感谢楼上几位热心的答复。结贴了。。。
 
多人接受答案了。
 

Similar threads

后退
顶部