让普通C++类轻松支持IDispatch自动化接口

2024-01-06 01:32

本文主要是介绍让普通C++类轻松支持IDispatch自动化接口,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

熟悉MFC和ATL/WTL的人一定都很熟悉它们的消息映射表,利用宏进行填表是一种非常简洁非常优雅的编码方式,通俗易懂维护方便。

         对于宏来说,使用越是简单,其内部构造就越复杂。很多人都说MFC把宏定义运用到了极致,以前我同意,现在有所保留,为什么?因为MFC的框架太古老了, 它使用的也是早期的宏特性。社会在发展,技术在进步,如今的标准已经对宏的特性进行了扩展。充分利用扩展的宏特性,能制作出更加简洁的代码。

    说了很多废话,言归正传。在大多数C++软件项目中,往往没有自动化需求,程序员通常会创造出下面的代码:

每个项目可能会出现一大堆的类定义,并且程序运作良好。忽然某一天,项目主管要求对代码执行自动化改造,或者为了制作出能在浏览器里执行的OCX控件,或者能被某些脚本语言调用,或者能嵌入到IIS中的ASP 页面内执行……,总之,老板想让WEB开发人员也能逗这条小狗(CDog)。

    我相信每个人针对这种需求都有这样一些感觉:我有很多改造方案,可是不管哪个方案,工作量都很大。MFC项目天然支持自动化,但它的个头太庞大了。ATL 也是纯种的自动化解决方案,但必须在纯种的ATL项目中才能使用它的各种向导功能,如果新建一个ATL项目,把这些现成的类搬进来再改造也不是一件容易的 事,尤其是涉及到类与类之间的继承关系调整。有些人可能会想直接利用ATL中的IDispatchImpl<>模板类,想法很好,但几乎实现 不了,因为IDispatchImpl内部严重依赖类型库,或者保存在注册表中,或者保存在程序资源中,总之IDL文件是必须要有的,而手工完成这些的工 作量还不如新建一个ATL项目来得划算。还有一种方法就是让CDog直接从IDispatch派生,然后实现IDispatch的所有7个方法,在它的 Invoke实现中根据DISPID不同分别访问CDog的成员变量或者调用成员函数,或者单独实现一个从IDispatch派生的类专门处理CDog, 但这种方式的工作量也是显而易见的,每个类都需要独立派生,或者每个类都需要创建一个对应的自动化支持类。

    超级无敌的宏现身了,这就是我的解决方案。它的最大好处就是用最小的代价完成自动化改造,你的现有项目可以是SDK/MFC/ATL,无需创建新项目,无 需IDL文件,无需类型库,无需注册组件。这种解决方案也是类似于消息映射宏,填表即可完成。还是以CDog的改造为例,老板希望这个dog具备Name 和Height属性,也具备Drink和Eat方法,那么使用宏解决方案,将会是下面的代码:

填完上面的表格,这个CDog已经可以被WEB开发人员牵出来遛了。顺便解释一下这个映射表的用法:

1、映射表以Begin_Disp_Map开始,唯一的参数就是需要改造的类CDog
2、映射表以End_Disp_Map结束
3、每一个属性或者方法占用一行表项
4、 属性的用法 Disp_Property(dispid, property_name, property_type),以 Disp_Property(1, Name, CString) 为例,属性的DISPID是1,属性的名称是Name,属性的类型是CString。这个宏表示Name属性是可读写的,如果属性只读(如Height) 应该用 Disp_PropertyGet,如果属性只写应该用 Disp_PropertyPut,参数的含义是一致的
5、 方法的用法 Disp_Method(dispid, method_name, return_type, param_count, param1_type, …, paramN_type),以 Disp_Method(3, Drink, void, 0) 为例,方法的DISPID是3,方法名称是Drink,方法函数返回值类型是void,方法没有参数。再看看 Disp_Method(4, Eat, bool, 2, long, long) 示例,方法的DISPID是4,方法名称是Eat,方法函数返回类型是bool,方法有2个参数,第一个参数类型是long,第二个参数类型是long

    这个自动化接口怎么用呢?通过下面的例子可以看出来,使用非常简单,因为映射宏暗中添加了 CDog::GetDispatch() 成员函数。

事 实上,我实现的自动化支持的宏定义曾经有两个版本,用法相似,但是实现方法完全不同。第一个版本采用的是自动创建类型库,然后通过 CreateStdDispatch() 函数创建 IDispatch 接口,这种方式有一些限制和缺陷,由于调用了API,我也不清楚内部有多少限制,因此导致第二个版本的诞生,这个版本完全在我自己的“掌控”中,可随时调 整和改造。此版本是一个独立的头文件macro.h,里面几乎全部是宏定义,还有几个作为辅助工具的模板类定义和数据结构。任何人都可以随意使用该文件, 也可以随意修改拷贝,不用交版税^_^。

    还有必要提醒一下这套解决方案的使用条件:

1、Windows平台,VC版本至少是2005,VC6/2003等早期版本不能使用。
2、用到了少量的ATL头文件,如果实际使用,可能需要自己添加对这些头文件的包含。
3、不依赖任何其它库,任何项目类型都可以使用。
4、变量类型请尽量使用VARIANT中支持的基础类型。

    如果用上面的示例代码进行实际的编译测试,你会发现编译通不过,原因在于 Name 的类型是 CString,这是一种其它库封装的高级类型,VARIANT不能识别。有两种解决方法:一种是懒人用的,把CString改成 CComBSTR,映射表中也需要对应修改;另一种是高级方法,这需要使用者完全理解了我实现的宏定义,通过自己创建特化模板类来扩充对 CString 的支持,例如 template<> class CVarTypeInfo< CString > { … };

    最后,我得申明一下,这套宏代码我自己一直在使用,而且一直在根据自己的实际需求改进和扩充,但本人没有义务一定要把最新改进版本贡献出来。 

    最后的最后,提供整个宏定义的 macro.h 头文件,自动化支持的部分可以直接被使用,宏的使用供有心人研究吧。



这篇关于让普通C++类轻松支持IDispatch自动化接口的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

C++中RAII资源获取即初始化

《C++中RAII资源获取即初始化》RAII通过构造/析构自动管理资源生命周期,确保安全释放,本文就来介绍一下C++中的RAII技术及其应用,具有一定的参考价值,感兴趣的可以了解一下... 目录一、核心原理与机制二、标准库中的RAII实现三、自定义RAII类设计原则四、常见应用场景1. 内存管理2. 文件操

C++中零拷贝的多种实现方式

《C++中零拷贝的多种实现方式》本文主要介绍了C++中零拷贝的实现示例,旨在在减少数据在内存中的不必要复制,从而提高程序性能、降低内存使用并减少CPU消耗,零拷贝技术通过多种方式实现,下面就来了解一下... 目录一、C++中零拷贝技术的核心概念二、std::string_view 简介三、std::stri

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP

华为鸿蒙HarmonyOS 5.1官宣7月开启升级! 首批支持名单公布

《华为鸿蒙HarmonyOS5.1官宣7月开启升级!首批支持名单公布》在刚刚结束的华为Pura80系列及全场景新品发布会上,除了众多新品的发布,还有一个消息也点燃了所有鸿蒙用户的期待,那就是Ha... 在今日的华为 Pura 80 系列及全场景新品发布会上,华为宣布鸿蒙 HarmonyOS 5.1 将于 7

C++作用域和标识符查找规则详解

《C++作用域和标识符查找规则详解》在C++中,作用域(Scope)和标识符查找(IdentifierLookup)是理解代码行为的重要概念,本文将详细介绍这些规则,并通过实例来说明它们的工作原理,需... 目录作用域标识符查找规则1. 普通查找(Ordinary Lookup)2. 限定查找(Qualif

详解如何使用Python构建从数据到文档的自动化工作流

《详解如何使用Python构建从数据到文档的自动化工作流》这篇文章将通过真实工作场景拆解,为大家展示如何用Python构建自动化工作流,让工具代替人力完成这些数字苦力活,感兴趣的小伙伴可以跟随小编一起... 目录一、Excel处理:从数据搬运工到智能分析师二、PDF处理:文档工厂的智能生产线三、邮件自动化: