使用 IDispatch 的 C++ 和 COM 的类似动态的替代方案

Posted

技术标签:

【中文标题】使用 IDispatch 的 C++ 和 COM 的类似动态的替代方案【英文标题】:Dynamic-like alternative for C++ and COM using IDispatch 【发布时间】:2013-04-13 00:24:23 【问题描述】:

我正在向一位同事展示使用Microsoft ATL library 在 C++ 中创建和使用 COM 对象是多么容易。特别是,我想使用演示IDispatch 来展示如何使用它来动态调用方法。但是,我没有足够频繁地使用 C++/ATL,以免迷失在 ATL 的模板、便捷方法和类中。

我们创建了一个小型 COM 类 MyCOMLibrary.SimpleClass,它有一个名为 AppendMessage 的方法,它需要 2 个 BSTRs 并且没有返回值。

从一个简单的 Win32 控制台应用程序,创建和使用 COM 对象很容易:

CComPtr<IDispatch> simpleClass;
debugPrint.CoCreateInstance(L"MyCOMLibrary.SimpleClass");
if (simpleClass) 
    CComVariant vModule(L"Demo");
    CComVariant vMessage(L"Welcome to COM");
    simpleClass.Invoke2(L"AppendMessage", &vModule, &vMessage);

虽然这使得创建和管理 COM 对象几乎没有痛苦(尤其是与使用 DISPPARAMS 相比),但我一直在寻找一种更简洁的方法来调用反映现代 C++/ATL/COM 用法的 AppendMessage 方法(在 VS 2012 中)。

最好的情况是 C# 的 dynamic 关键字 (dynamic documentation)(或任何其他“后期绑定”语言,如 javascript/VB6/等):

simpleClass.AppendMessage(L"Demo", L"Welcome to COM"); 

或者,没有它,这将更具可读性:

simpleClass.Invoke2(L"AppendMessage", L"Demo", L"Welcome to COM");

但是,我知道第一个不会编译,因为CComPtr&lt;IDispatch&gt; 上不存在该方法,第二个不会编译,因为Invoke2 需要VARIANTs。

我确实尝试过直接使用界面作为比较:

// workaround VS2012 intellisense issue with #import
#ifndef __INTELLISENSE__
    #import "progid:MyCOMLibrary.ISimpleClass" version("1.0")
#else
    #include "Debug\MyCOMLibrary.tlh"
#endif

CComPtr<MyCOMLibrary::ISimpleClass> simpleClass;
simpleClass.CoCreateInstance(L"MyCOMLibrary.ISimpleClass");
if (simpleClass) 
    CComBSTR module(L"Interfacing");
    CComBSTR message(L"And, then, there was COM.");
    simpleClass->AppendMessage((BSTR)module, (BSTR)message);

但是,它几乎与原版相同(而且,我想做后期绑定)。

问题

使用IDispatch 和ATL 调用AppendMethod 是否有不同/更短/更好/很棒的方式,这会进一步让我的同事意识到C++ 并不总是很困难? (或者,没有 ATL 的更好方法也可以)。

【问题讨论】:

一个很棒的替代方案可能是 #import 类型库并通过早期绑定直接使用感兴趣的接口。我认为 2012 年甚至 2010 年都没有为 ATL 增加任何令人印象深刻的内容。 @RomanR。 - 我也在尝试#import 选项(尽管我确实想使用IDispatch 作为演示的一部分)。然而#import 显然并不像文档所暗示的那么简单,因为 Intellisense 和#import 存在一些错误/问题 这对我来说是个新闻。也许你应该问一个关于它的问题。 @HansPassant - 我在我的问题中添加了#import 解决方法的详细信息(我在 MS Connect 网站上找到了解决方法的建议) 为什么不将CComVariantInvoke2 一起使用? 【参考方案1】:

看看马修·威尔逊的 VOLE。

在http://vole.sourceforge.net/

它认为它做你想做的事。我以前用过它,它使 IDispatch 客户端编程变得轻而易举。

查看http://www.codeproject.com/Articles/19962/Driving-Microsoft-Word-using-VOLE 以了解使用 Microsoft World 的示例

【讨论】:

以上是关于使用 IDispatch 的 C++ 和 COM 的类似动态的替代方案的主要内容,如果未能解决你的问题,请参考以下文章

创建 IDispatch .NET COM 类,其中内容仅在运行时可用

如何将 IDispatch::Invoke 放入 MFC C++ 线程?

通过 CComPtr<IDispatch> Invoke 检索数组

对于进程间 COM 对象,在不使用 QueryInterface 的情况下将 IDispatch* 转换为 IUnknown* 是不是安全?

在 C# 中实现 DISPID_VALUE 并从 C++ 中调用它

COM技术入门