使用 COleDispatchDriver 的 MFC COM 包装代码生成器





5.00/5 (7投票s)
IDispatch C++ 代码生成得当
引言
随着 REST 接口接管世界,微软对其原生代码工具的关注越来越少。最新的 COleDispatchDriver
代码生成器简直是一场灾难,生成的代码甚至无法编译。幸运的是,我已经编写了自己的生成器来解决历史遗留问题,这也是我完成 2018 年开始的开源版本的最后动力。
背景
这个代码生成器的目标是
- 完美解析从 OLE Viewer 生成的 IDL
- 自动使用库名称作为
namespace
- 将
helpstring
作为库的注释输出 - 生成
enum
声明 - 在函数上输出
enum
名称(而不是long
) - 当它无法识别类型时输出
VARIANT
,而不是一条说明该函数无法支持的注释 - 为所有内容输出实际类型,而不是
IDispatch
- 支持 COM 事件代码生成
Using the Code
首先,您需要访问 oleview.exe。您可以在 Windows SDK 中找到它。例如,在我的机器上,EXE 文件位于 C:\Program Files (x86)\Windows Kits\10\bin\10.0.20348.0\\x64\oleview.exe。请注意,您可能需要使用命令 regsvr32 iviewers.dll 以管理员身份注册 iviewers.dll。
现在在 OLE Viewer 中选择一个接口(例如,Microsoft XML)并查看 IDL
使用 Ctrl-A 选择所有代码,然后将其粘贴到文本文件中并保存,扩展名为 .idl。
对通过 IDL 中的 importlib
命令导入的任何类型库递归重复此过程(在本例中为 stdole2.tlb)。
您现在可以在 .idl 文件上运行 idl2cpp.exe
。
例如
idl2cpp XML.idl
如果这样运行,没有任何开关,您应该只会收到一条消息,说明文件已成功解析。要输出一些代码,您可以选择
- /enums
- /events_h
- /events_cpp
- /fwd_decls
- /h
- /cpp
请注意,这些开关是互斥的。
最好先将 enum
s 和前向声明输出到两个单独的文件中,然后创建头文件并 #include
这两个文件。
例如
idl2cpp XML.idl /enums > msxml2_enums.h
idl2cpp XML.idl /fwd_decls > msxml2_fwd_decls.h
idl2cpp XML.idl /h > msxml2.h
最后,您可以输出 cpp 文件
idl2cpp XML.idl /cpp > msxml2.cpp
输出
以下是您可能期望的输出示例
msxml2_enums.h
#pragma once
// GENERATED CODE by idl2cpp 2022-06-19 13:26:24
namespace MSXML2
{
// Schema Object Model Content Types
enum class _SCHEMACONTENTTYPE
{
SCHEMACONTENTTYPE_EMPTY = 0,
SCHEMACONTENTTYPE_TEXTONLY = 1,
SCHEMACONTENTTYPE_ELEMENTONLY = 2,
SCHEMACONTENTTYPE_MIXED = 3
};
...
msxml2_fwd_decls.h
#pragma once
// GENERATED CODE by idl2cpp 2022-06-19 13:27:25
namespace MSXML2
{
struct IXMLDOMNode;
struct IXMLDOMNodeList;
struct IXMLDOMNamedNodeMap;
...
msxml2.h
#pragma once
// GENERATED CODE by idl2cpp 2022-06-19 13:29:27
// http://support.microsoft.com/kb/134980
#pragma warning(push)
#pragma warning(disable:4275)
// Microsoft XML, v6.0
namespace MSXML2
{
using DOMNodeType = tagDOMNodeType;
using SCHEMACONTENTTYPE = _SCHEMACONTENTTYPE;
using SCHEMADERIVATIONMETHOD = _SCHEMADERIVATIONMETHOD;
using SCHEMAPROCESSCONTENTS = _SCHEMAPROCESSCONTENTS;
using SCHEMATYPEVARIETY = _SCHEMATYPEVARIETY;
using SCHEMAUSE = _SCHEMAUSE;
using SCHEMAWHITESPACE = _SCHEMAWHITESPACE;
using SERVERXMLHTTP_OPTION = _SERVERXMLHTTP_OPTION;
using SOMITEMTYPE = _SOMITEMTYPE;
using SXH_PROXY_SETTING = _SXH_PROXY_SETTING;
using SXH_SERVER_CERT_OPTION = _SXH_SERVER_CERT_OPTION;
using XHR_PROPERTY = _XHR_PROPERTY;
// Core DOM node interface
struct AFX_EXT_CLASS IXMLDOMNode : COleDispatchDriver
{
IXMLDOMNode() {}
IXMLDOMNode(LPDISPATCH pDispatch) :
COleDispatchDriver(pDispatch) {}
IXMLDOMNode(const IXMLDOMNode& dispatchSrc) :
COleDispatchDriver(dispatchSrc) {}
CString GetnodeName();
VARIANT GetnodeValue();
void SetnodeValue(const VARIANT& newValue);
...
msxml2.cpp
// GENERATED CODE by idl2cpp 2022-06-19 13:30:45
namespace MSXML2
{
CString IXMLDOMNode::GetnodeName()
{
CString result{};
InvokeHelper(0x2, DISPATCH_PROPERTYGET, VT_BSTR, &result, nullptr);
return result;
}
VARIANT IXMLDOMNode::GetnodeValue()
{
VARIANT result{};
InvokeHelper(0x3, DISPATCH_PROPERTYGET, VT_VARIANT, &result, nullptr);
return result;
}
...
请注意,自动生成的头文件包含 #include
s 语句,用于 msxml2_enums.h 和 msxml2_fwd.h。
生成的源文件还将自动包含 #include
语句,用于 msxml2.h。
目前,/events_cpp 的生成器要求手动添加对应头文件的 #include
。
历史
- 2022年6月19日:创建
- 2022年6月19日:将缺失的文件添加到 zip 文件中
- 2022年6月19日:停止将
int
转换为long
作为返回值 - 2022年6月19日:添加了开关
/events_h
和/events_cpp
- 2022年6月19日:输出
nullptr
而不是0
作为指针的默认值 - 2022年6月24日:各种错误修复
- 2022年7月2日:添加了对函数
helpstring
的支持 - 2022年7月2日:一致地处理
CURRENCY
和VARIANT
。仅在仅为in
参数时才使用const
- 2022年7月4日:
int64
和uint64
不应创建注释 - 2022年7月4日:将可选参数默认为
0
/nullptr
,如果没有指定值 - 2022年10月19日:修复了 output_header.cpp 中的断开链接
- 2023年1月21日:更新为使用最新的
parsertl
- 2023年1月31日:更新为使用最新的
parsertl
- 2023年9月11日:更新了
lexertl
、parsertl
和Makefile
。修复了一些 g++ 警告 - 2023年12月2日:现在尽可能输出实际类型,而不是一直使用
IDispatch*
- 2023年12月5日:将运算符
LPDISPATCH
设置为delete
并自动输出#include
s - 2023年12月10日:改进了事件源代码生成的注释。还进行了 SonarLint 建议的更改
- 2023年12月22日:添加了
/name
开关,以便可以输出单个接口 - 2023年12月26日:向
events_template.cpp
添加了缺失的换行符 - 2024年2月15日:更新为使用 lexertl17 和 parsertl17
- 2024年4月6日:添加了更多解释。
- 2024年4月7日:现在正确处理
coclass
参数。