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

相关文章

SpringBoot实现RSA+AES自动接口解密的实战指南

《SpringBoot实现RSA+AES自动接口解密的实战指南》在当今数据泄露频发的网络环境中,接口安全已成为开发者不可忽视的核心议题,RSA+AES混合加密方案因其安全性高、性能优越而被广泛采用,本... 目录一、项目依赖与环境准备1.1 Maven依赖配置1.2 密钥生成与配置二、加密工具类实现2.1

使用Python的requests库调用API接口的详细步骤

《使用Python的requests库调用API接口的详细步骤》使用Python的requests库调用API接口是开发中最常用的方式之一,它简化了HTTP请求的处理流程,以下是详细步骤和实战示例,涵... 目录一、准备工作:安装 requests 库二、基本调用流程(以 RESTful API 为例)1.

Python调用LibreOffice处理自动化文档的完整指南

《Python调用LibreOffice处理自动化文档的完整指南》在数字化转型的浪潮中,文档处理自动化已成为提升效率的关键,LibreOffice作为开源办公软件的佼佼者,其命令行功能结合Python... 目录引言一、环境搭建:三步构建自动化基石1. 安装LibreOffice与python2. 验证安装

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么

小白也能轻松上手! 路由器设置优化指南

《小白也能轻松上手!路由器设置优化指南》在日常生活中,我们常常会遇到WiFi网速慢的问题,这主要受到三个方面的影响,首要原因是WiFi产品的配置优化不合理,其次是硬件性能的不足,以及宽带线路本身的质... 在数字化时代,网络已成为生活必需品,追剧、游戏、办公、学习都离不开稳定高速的网络。但很多人面对新路由器

Spring Boot从main方法到内嵌Tomcat的全过程(自动化流程)

《SpringBoot从main方法到内嵌Tomcat的全过程(自动化流程)》SpringBoot启动始于main方法,创建SpringApplication实例,初始化上下文,准备环境,刷新容器并... 目录1. 入口:main方法2. SpringApplication初始化2.1 构造阶段3. 运行阶

SpringBoot+EasyPOI轻松实现Excel和Word导出PDF

《SpringBoot+EasyPOI轻松实现Excel和Word导出PDF》在企业级开发中,将Excel和Word文档导出为PDF是常见需求,本文将结合​​EasyPOI和​​Aspose系列工具实... 目录一、环境准备与依赖配置1.1 方案选型1.2 依赖配置(商业库方案)二、Excel 导出 PDF

从入门到进阶讲解Python自动化Playwright实战指南

《从入门到进阶讲解Python自动化Playwright实战指南》Playwright是针对Python语言的纯自动化工具,它可以通过单个API自动执行Chromium,Firefox和WebKit... 目录Playwright 简介核心优势安装步骤观点与案例结合Playwright 核心功能从零开始学习