进程内COM对象的创建过程(AC5)

2024-03-05 03:48
文章标签 创建 对象 进程 过程 com ac5

本文主要是介绍进程内COM对象的创建过程(AC5),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

AC5,由VS2005的ATL向导生成的默认COM对象代码分析ATL如何实现COM,第五部分。

  Com库创建COM对象可以使用三个方法:

[csharp]  view plain copy
  1. CoCreateInstance(IN REFCLSID rclsid, IN LPUNKNOWN pUnkOuter, IN DWORD dwClsContext, IN REFIID riid, OUT LPVOID FAR* ppv);  
  2.   
  3. CoCreateInstanceEx(IN REFCLSID Clsid, IN IUnknown * punkOuter, IN DWORD dwClsCtx, IN COSERVERINFO * pServerInfo, IN DWORD dwCount, IN OUT MULTI_QI * pResults );  
  4.   
  5. CoGetClassObject(IN REFCLSID rclsid, IN DWORD dwClsContext, IN LPVOID pvReserved, IN REFIID riid, OUT LPVOID FAR* ppv);  

  常用的是CoCreateInstance,内部实现上,CoCreateInstance和CoCreateInstanceEx都先调用CoGetClassObject,可以说,CoGetClassObject是Com库创建com对象第一个被调用的方法。

  具体的调用过程是这样的:  

  1.CoCreateInstance调用CoGetClassObject函数

   2.COM库找到dll程序并进入进程

   3.调用DllGetClassObject函数

   4.DllGetClassObject函数创建类厂

   5.DllGetClassObject函数把类厂接口返回给CoGetClassObject函数

   6.CoGetClassObject函数把类厂返回给CoCreateInstance函数

   7.CoCreateInstace函数得到类厂后,调用类厂的对象创建函数

   8.类厂创建COM对象

   9.类厂把COM对象返回给CoCreateInstance函数,CoCreateInstance函数返回

   10.客户直接调用COM对象 

  从ATL COM服务器的角度上来说:

  加载dll阶段

  1._DllMainCRTStartup

   2.DoInitialization初始化CAtlComModule、_AtlBaseModule、_AtlWinModule、_Module

   3.CoCreateInstance调用CoGetClassObject函数

  4.dll函数DllGetClassObject被调用

  5.转到_AtlModule.DllGetClassObject(CAtlDllModuleT< Your_COM_Module >::DllGetClassObject)

   6.CAtlDllModuleT< Your_COM_Module >:: GetClassObject

  7.ATLAPI AtlComModuleGetClassObject(&_AtlComModule作为pComModule参数)

  8.找到预先保存的ATL¥__m中的_ATL_OBJMAP_ENTRY指针

  9.XXX:: _ClassFactoryCreatorClass::CreateInstance(通过映射表获得)

  10.CComCreator:: CreateInstance

   11.new CComObjectCached< CComClassFactory >

   12.给CComClassFactory对象设置创建com对象方法(SetVoid方法设置了CreateInstance里要使用到的指针,别忘了CComClassFactory的CreateInstance是非静态的)

  13.CComClassFactory对象的IUnknown接口(使用了QI方法)其实就是IClassFactory的IUnknow接口了

  14.使用IClassFactory的IUnknown查询到IClassFactory接口

  15.逐层返回到DllGetClassObject

  16.CoCreateInstance得到了类厂接口

  17.CoCreateInstance调用类厂的CreateInstance方法(该CreateInstance非静态,所以必须使用类厂接口调用)

  18.因为之前我们已经给类厂对象保存了com对象的CreateInstance指针(该方法为静态,在CoComCreator2中),所以CoComCreator2直接向两个CoComCreator转发CreateInstance请求。(根据pOuter,如果非聚合,使用CComObject,聚合的话,则使用CComAggObject)

  19.(不聚合)CComObject<XXX>::CreateInstance(该方法为静态方法),该类不处理聚合情况,所以pOuter传入NUL

   19.(聚合)CComAggObject同CComObject相比,不同点在QI,CComObject是自己直接调用查询方法,而CComAggObject则是把请求转发给pOuter,在CComAggObject的构造函数中,pOuter被赋值给了m_contained,该指针类型为CComContainedObject<contained>,实际转发工作由这个类完成。通过_InternalQueryInterface,对,我说过定义这个函数的宏。

  20.(不聚合)按照CoComCreator的定式,调用setVoid方法,但CoComObject没有定义setVoid方法,所以向基类XXX求助,XXX转向CComObjectRootEx而后CComObjectRootBase,终于找到了setVoid方法。(可惜这个方法什么也不做,不过我们传递的参数也是NUL,互相“欺诈”贝丷丷)

  21.CComCreator例行公事的调用了_AtlInitialConstruct 、FinalConstruct、_AtlFinalConstruct方法,当然这些方法都是“欺诈行为”,不过可喜的是FinalConstruct在我们定义的类里,我们可以在这里定制一些初始化时的行为。

   22.CComCreator调用QI方法,这次传递的参数是我们在使用CoCreateInstance时传递的参数,因而用户的接口查询请求在这里完成。

这篇关于进程内COM对象的创建过程(AC5)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/775242

相关文章

oracle 11g导入\导出(expdp impdp)之导入过程

《oracle11g导入导出(expdpimpdp)之导入过程》导出需使用SEC.DMP格式,无分号;建立expdir目录(E:/exp)并确保存在;导入在cmd下执行,需sys用户权限;若需修... 目录准备文件导入(impdp)1、建立directory2、导入语句 3、更改密码总结上一个环节,我们讲了

ShardingProxy读写分离之原理、配置与实践过程

《ShardingProxy读写分离之原理、配置与实践过程》ShardingProxy是ApacheShardingSphere的数据库中间件,通过三层架构实现读写分离,解决高并发场景下数据库性能瓶... 目录一、ShardingProxy技术定位与读写分离核心价值1.1 技术定位1.2 读写分离核心价值二

MyBatis-plus处理存储json数据过程

《MyBatis-plus处理存储json数据过程》文章介绍MyBatis-Plus3.4.21处理对象与集合的差异:对象可用内置Handler配合autoResultMap,集合需自定义处理器继承F... 目录1、如果是对象2、如果需要转换的是List集合总结对象和集合分两种情况处理,目前我用的MP的版本

Java Kafka消费者实现过程

《JavaKafka消费者实现过程》Kafka消费者通过KafkaConsumer类实现,核心机制包括偏移量管理、消费者组协调、批量拉取消息及多线程处理,手动提交offset确保数据可靠性,自动提交... 目录基础KafkaConsumer类分析关键代码与核心算法2.1 订阅与分区分配2.2 拉取消息2.3

Spring创建Bean的八种主要方式详解

《Spring创建Bean的八种主要方式详解》Spring(尤其是SpringBoot)提供了多种方式来让容器创建和管理Bean,@Component、@Configuration+@Bean、@En... 目录引言一、Spring 创建 Bean 的 8 种主要方式1. @Component 及其衍生注解

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优

使用Java读取本地文件并转换为MultipartFile对象的方法

《使用Java读取本地文件并转换为MultipartFile对象的方法》在许多JavaWeb应用中,我们经常会遇到将本地文件上传至服务器或其他系统的需求,在这种场景下,MultipartFile对象非... 目录1. 基本需求2. 自定义 MultipartFile 类3. 实现代码4. 代码解析5. 自定

AOP编程的基本概念与idea编辑器的配合体验过程

《AOP编程的基本概念与idea编辑器的配合体验过程》文章简要介绍了AOP基础概念,包括Before/Around通知、PointCut切入点、Advice通知体、JoinPoint连接点等,说明它们... 目录BeforeAroundAdvise — 通知PointCut — 切入点Acpect — 切面

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数

MySQ中出现幻读问题的解决过程

《MySQ中出现幻读问题的解决过程》文章解析MySQLInnoDB通过MVCC与间隙锁机制在可重复读隔离级别下解决幻读,确保事务一致性,同时指出性能影响及乐观锁等替代方案,帮助开发者优化数据库应用... 目录一、幻读的准确定义与核心特征幻读 vs 不可重复读二、mysql隔离级别深度解析各隔离级别的实现差异