让普通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

相关文章

利用c++判断水仙花数并输出示例代码

《利用c++判断水仙花数并输出示例代码》水仙花数是指一个三位数,其各位数字的立方和恰好等于该数本身,:本文主要介绍利用c++判断水仙花数并输出的相关资料,文中通过代码介绍的非常详细,需要的朋友可以... 以下是使用C++实现的相同逻辑代码:#include <IOStream>#include <vec

基于C++的UDP网络通信系统设计与实现详解

《基于C++的UDP网络通信系统设计与实现详解》在网络编程领域,UDP作为一种无连接的传输层协议,以其高效、低延迟的特性在实时性要求高的应用场景中占据重要地位,下面我们就来看看如何从零开始构建一个完整... 目录前言一、UDP服务器UdpServer.hpp1.1 基本框架设计1.2 初始化函数Init详解

Mybatis对MySQL if 函数的不支持问题解读

《Mybatis对MySQLif函数的不支持问题解读》接手项目后,为了实现多租户功能,引入了Mybatis-plus,发现之前运行正常的SQL语句报错,原因是Mybatis不支持MySQL的if函... 目录MyBATis对mysql if 函数的不支持问题描述经过查询网上搜索资料找到原因解决方案总结Myb

C#实现将XML数据自动化地写入Excel文件

《C#实现将XML数据自动化地写入Excel文件》在现代企业级应用中,数据处理与报表生成是核心环节,本文将深入探讨如何利用C#和一款优秀的库,将XML数据自动化地写入Excel文件,有需要的小伙伴可以... 目录理解XML数据结构与Excel的对应关系引入高效工具:使用Spire.XLS for .NETC

C++ 右值引用(rvalue references)与移动语义(move semantics)深度解析

《C++右值引用(rvaluereferences)与移动语义(movesemantics)深度解析》文章主要介绍了C++右值引用和移动语义的设计动机、基本概念、实现方式以及在实际编程中的应用,... 目录一、右值引用(rvalue references)与移动语义(move semantics)设计动机1

Java利用Spire.XLS for Java自动化设置Excel的文档属性

《Java利用Spire.XLSforJava自动化设置Excel的文档属性》一个专业的Excel文件,其文档属性往往能大大提升文件的可管理性和可检索性,下面我们就来看看Java如何使用Spire... 目录Spire.XLS for Java 库介绍与安装Java 设置内置的 Excel 文档属性Java

Python自动化提取多个Word文档的文本

《Python自动化提取多个Word文档的文本》在日常工作和学习中,我们经常需要处理大量的Word文档,本文将深入探讨如何利用Python批量提取Word文档中的文本内容,帮助你解放生产力,感兴趣的小... 目录为什么需要批量提取Word文档文本批量提取Word文本的核心技术与工具安装 Spire.Doc

C#高效实现在Word文档中自动化创建图表的可视化方案

《C#高效实现在Word文档中自动化创建图表的可视化方案》本文将深入探讨如何利用C#,结合一款功能强大的第三方库,实现在Word文档中自动化创建图表,为你的数据呈现和报告生成提供一套实用且高效的解决方... 目录Word文档图表自动化:为什么选择C#?从零开始:C#实现Word文档图表的基本步骤深度优化:C

C++ move 的作用详解及陷阱最佳实践

《C++move的作用详解及陷阱最佳实践》文章详细介绍了C++中的`std::move`函数的作用,包括为什么需要它、它的本质、典型使用场景、以及一些常见陷阱和最佳实践,感兴趣的朋友跟随小编一起看... 目录C++ move 的作用详解一、一句话总结二、为什么需要 move?C++98/03 的痛点⚡C++

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处