首页 通过COM接口得到实现该接口的对象实例

通过COM接口得到实现该接口的对象实例

举报
开通vip

通过COM接口得到实现该接口的对象实例通过COM接口得到实现该接口的对象实例 如何通过COM接口得到实现该接口的对象实例 问题由来 我的程序为一个基于COM的插件结构,框架需要向插件传递一个IResource接口。IResource 需要根据不同的插件传递不同的内容。 接口定义 IResource = Interface(IDispatch) Function GetPath: String; safecall; End; 实现类 TResource = TClass(TAutoObject, IResource) protected...

通过COM接口得到实现该接口的对象实例
通过COM接口得到实现该接口的对象实例 如何通过COM接口得到实现该接口的对象实例 问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 由来 我的程序为一个基于COM的插件结构,框架需要向插件传递一个IResource接口。IResource 需要根据不同的插件传递不同的 内容 财务内部控制制度的内容财务内部控制制度的内容人员招聘与配置的内容项目成本控制的内容消防安全演练内容 。 接口定义 IResource = Interface(IDispatch) Function GetPath: String; safecall; End; 实现类 TResource = TClass(TAutoObject, IResource) protected Function GetPath: String; SafeCall; Public Path: String; End; Function GetPath: String; Begin Result:= Path; End; 调用部分: Var Resource: IResource; ResourceObj: TResource; Begin Resource:= CreateComObject(CLASS_Resource) As IResource; //想通过强制转换得到TResource;结果失败了:( ResourceObj:= TResource(Resource); ResourceObj.Path:= '这里设置不同的值'; End; 请问: 如何通过IResource得到TResource,从而达到设置PATH值的目的? 目前我采用的 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 是再定义一个ISetValue的接口修改里面的PATH属性,感觉用起来比较 麻烦。 问题的延伸 如果从解决问题出发,通过定义配置接口,如: IObjRef = Interface function GetObjRef: TObject; safecall; end; 这样得到对象,再对PATH赋值,这样做在没有破坏COM的封装,实现起来也比较清晰。 问题至此基本解决。 但本着从 分析 定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析 DELPHI对象与接口之间的关系的出发点,我们还是继续标题中提出的问题: 如何通过COM接口得到实现该接口的对象实例 , 关于DELPHI中对象与接口之间在编译器实现的内存空间情况: -------------------------------------------------------------------------- 对象/接口指针 对象内存空间 虚 方法 快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载 表 -------------------------------------------------------------------------- MyObject -> VMTptr 00---------> VirtA 00 FRefCount 04 VirtB 04 MyIntf -> IInterface 08---- FFieldA 0C IInterface 跳转表 FFieldB 10 ---------> addr of QueryInterface MyIntfB -> IIntfB 14--------- addr of _AddRef MyIntfA -> IIntfA 18-- addr of _Release IIntfB 跳转表 ----> addr of ProcB addr of VirtB IIntfA 跳转表 -----------> addr of ProcA addr of VirtA ------------------------------------------------------------------------------ 一个对象在调用类的成员函数的时候,比如执行 MyObject.ProcA,会隐含传递一个 Self 指 针给这个成员函数:MyObject.ProcA(Self)。Self 就是对象数据空间的地址。那么编译器如 何知道 Self 指针,原来对象指针 MyObject 指向的地址就是 Self,编译器直接取出 MyObject^ 就可以作为 Self。 在以接口的方式调用成员函数的时候,比如 MyIntfA.ProcA,这时编译器不知道 MyIntfA 到底指向哪种类型(class)的对象,无法知道 MyIntfA 与 Self 之间的距离(实际上,在上面 的例子中 Delphi 编译器知道 MyIntfA 与 Self 之间的距离,只是为了与 COM 的二进制 格式兼容,使其它语言也能够使用接口指针调用接口成员函数,必须使用后期的 Self 指针 修正),编译器直接把 MyIntfA 指向的地址设置为 Self。从上图可以看到,MyIntfA 指向 MyObject 对象空间中 $18 偏移地址。这时的 Self 指针当然是错误的,编译器不能直接调用 TMyObject.ProcA,而是调用 IIntfA 的“接口跳转表”中的 ProcA。“接口跳转表”中的 ProcA 的内容就是对 Self 指针进行修正(Self - $18),然后再调用 TMyObject.ProcA,这时就是正确调用对象的成员函数了。由于每个类实现接口的顺序不一定相同,因此对于相同的接口在不同的类中实现,就有不同的接口跳转表(当然,可能编辑器能够聪明地检查到一些类的“接口跳转表”偏移量相同,也可以共享使用)。 通过这里得到了解决问题的关键,如果能得到接口的偏移地址,那么就可以得到对象实例 呵呵,,看到曙光了,加油~ 寻找偏移地址 众所周知,所有的DELPHI对象都是从TObject继承下来的,而创建对象也是通过 class function TObject.InitInstance(Instance: Pointer): TObject; 来分配内存空间的,仔细分析这段代码。 class function TObject.InitInstance(Instance: Pointer): TObject; {$IFDEF PUREPASCAL} var IntfTable: PInterfaceTable; ClassPtr: TClass; I: Integer; begin FillChar(Instance^, InstanceSize, 0); PInteger(Instance)^ := Integer(Self); ClassPtr := Self; while ClassPtr <> nil do begin IntfTable := ClassPtr.GetInterfaceTable; if IntfTable <> nil then for I := 0 to IntfTable.EntryCount-1 do with IntfTable.Entries[I] do begin if VTable <> nil then //就是它了IOffset,它就是接口的偏移地址 PInteger(@PChar(Instance)[IOffset])^ := Integer(VTable); end; ClassPtr := ClassPtr.ClassParent; end; Result := Instance; end; 找到了IOffset,在跟踪发现它属于 接口标识的接口项(PInterfaceEntry) PInterfaceEntry = ^TInterfaceEntry; TInterfaceEntry = packed record IID: TGUID; VTable: Pointer; IOffset: Integer; ImplGetter: Integer; end; 问题出来了,得到PInterfaceEntry 就得到了一切 轻松得到PInterfaceEntry Var eResourceObj: TResource; eEntry: PInterfaceEntry; eAutoObjFactory: TAutoObjectFactory; Begin eResource:= CreateComObject(CLASS_Resource) as IResource; //得到类工厂 eAutoObjFactory:= TAutoObjectFactory(ComClassManager.GetFactoryFromClassID(CLASS_Resource)); //得到接口标识的接口项 eEntry:= eAutoObjFactory.DispIntfEntry; //IOffset为接口的偏移地址,eResource减去IOffset所得到的地址就是对象实例 eResourceObj:= TResource(Integer(eResource)-eEntry.IOffset); eResourceObj.Path:= '这里设置不同的值''; End; 结论 费劲周折得来的结果,可能对整个问题并没有太多的意义。但是,过程确实非常有意义,通过这个过程让我对DELPHI对象和接口的实质有了更深层次的了解。
本文档为【通过COM接口得到实现该接口的对象实例】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_713593
暂无简介~
格式:doc
大小:21KB
软件:Word
页数:0
分类:企业经营
上传时间:2018-04-18
浏览量:21