CoCreateInstance调用COM接口伪流程

在编写组件程序时,经常会使用CoCreateInstance直接取COM组件的接口,非常方便,那CoCreateInstance到底干了些什么事呢?1、CoCreateInstance取COM组件的接口的基本流程

//参数:rclsid = 组件CLSID
//参数:riid = 接口ID
WINOLEAPI   CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, 
                             DWORD dwClsContext, REFIID riid, LPVOID FAR* ppICOMInterface)
{
        //根据组件的CLSID从注册表中取Dll的地址,并加载
        char        pszCOMDllPath;
        SHGetValue(HKEY_CLASSES_ROOT, "CLSID+rclsid\InprocServer32", "默认", pszCOMDllPath);
        LoadLibrary(pszCOMDllPath);

        //调用DllGetClassObject,创建IID_IClassFactory总接口
        IClassFactory* pIF
<think>嗯,用户想了解COM组件编程的相关知识。从用户提供的站内引用来看,用户似乎更关注COM的实用性和简化实现,而非底层理论。引用[1]提到“简化COM以降低编程门槛”,引用[2]则概述了COM的核心接口,这说明用户需要的是实用导向的知识。 注意到用户上次讨论过快速排序的实现方式,可能偏好具体技术细节的拆解。因此回应时应该突出三点:核心概念(IUnknown等)、简化开发的关键点(如不用注册的组件创建)、与传统面向对象的区别。避免深入GUID、跨公寓调用等进阶内容,重点放在“如何用COM思想写可复用模块”。 用户引用的Vue组件化例子很有意思,可以类比说明——就像Vue的组件需要注册后才能在模板使用,COM组件也需要注册才能被调用。但COM更底层,Vue组件间通信靠props/events,而COM接口指针。 特别要强调ATL库的作用,因为引用[1]提到“避免巨大代价”,而ATL正是解决这个痛点的工具。给出CoCreateInstance代码示例比理论描述更直观,用户上次对快速排序的代码示例就有积极反馈。 最后预留的问题要回应引用[3]隐含的组件化对比需求(如CORBA),但保持聚焦COM。不提及IDispatch这类高级话题,用户当前明显处于入门阶段。 </think>以下是COM组件编程的核心知识框架,结合关键概念和实际开发要点整理而成: --- ### **一、COM的核心思想** 1. **二进制重用** COM组件以二进制形式(DLL/EXE)存在,不同语言(C++/C#/Delphi)开发的组件可直接互调,无需源码重编译[^2]。 2. **接口契约** 组件功能通过接口(纯虚类)暴露,调用方仅依赖接口而非具体实现类。 3. **位置透明性** 本地与远程组件调用方式一致(通过DCOM实现跨进程/网络通信)。 --- ### **二、COM组件三大基础接口** | 接口 | 作用 | |-----------------|----------------------------------------------------------------------| | **IUnknown** | 所有接口的基类,提供`QueryInterface()`(接口查询)和引用计数管理[^2] | | **IClassFactory** | 创建组件实例,实现`CreateInstance()`方法 | | **IDispatch** | 支持后期绑定(如脚本语言调用),通过`Invoke()`动态调用方法 | > ✅ **关键机制**: > - **引用计数**:组件生命周期通过`AddRef()`/`Release()`控制 > - **接口查询**:`QueryInterface(IID, &ppv)`按需获取组件功能 --- ### **三、简化COM开发的实践方案** 针对引用[1]中“降低门槛”的需求: 1. **使用ATL(Active Template Library)** ```cpp // ATL简化COM对象创建示例 class ATL_NO_VTABLE CMyComponent : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CMyComponent, &CLSID_MyComponent>, public IMyInterface { public: DECLARE_REGISTRY_RESOURCEID(IDR_MYCOMPONENT) BEGIN_COM_MAP(CMyComponent) COM_INTERFACE_ENTRY(IMyInterface) END_COM_MAP() // 接口方法实现... }; ``` ATL自动处理引用计数、接口映射等样板代码。 2. **免注册激活(Registration-Free COM)** 通过清单文件(Manifest)局部注册组件,避免全局注册表污染[^1]。 3. **聚焦核心接口** 非通用场景可省略`IDispatch`,仅实现必要业务接口。 --- ### **四、COM vs 现代组件化技术** | 特性 | COM | Vue组件[^4] | CORBA[^3] | |---------------------|-------------------|-------------------|-------------------| | **通信方式** | 二进制接口指针 | Props/Events | ORB远程调用 | | **语言支持** | 多语言 | JavaScript | 多语言 | | **部署复杂度** | 高(需注册) | 低(模块化打包) | 高(ORB配置) | | **适用场景** | 系统级模块复用 | 前端UI复用 | 分布式企业系统 | > 💡 **COM的现代替代**: > - .NET程序集(Assembly)提供更简单的版本控制和安全模型 > - WebAssembly实现浏览器环境二进制组件 --- ### **五、开发流程关键步骤** 1. **定义接口**(IDL文件) ```idl interface IMath : IUnknown { HRESULT Add([in] int a, [in] int b, [out, retval] int* result); } ``` 2. **实现组件类**(继承接口并实现方法) 3. **注册组件**(`RegSvr32`或清单文件) 4. **客户端调用**: ```cpp IMath* pMath = nullptr; CoCreateInstance(CLSID_MathComponent, NULL, CLSCTX_INPROC_SERVER, IID_IMath, (void**)&pMath); pMath->Add(3, 5, &result); // 调用接口方法 ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值