在 C++ 中转换 COM 类型

Posted

技术标签:

【中文标题】在 C++ 中转换 COM 类型【英文标题】:Casting COM types in C++ 【发布时间】:2016-07-25 14:21:47 【问题描述】:

我有以下 COM 类型:ProjectContainerItemNodeProject 有一个集合属性,该属性带有一个接受 ContainerItems 的 Append 函数。

在 C# 中,使用类型库我可以将 Node 对象发送到 Append 函数并且库按预期工作:

var prj = new Project();
var node = new Node();
prj.collection.Append(node);

在 C++ 中,我尝试了直接指针转换,期望这是 C# 正在做的事情,但它最终导致错误:

ProjectPtr prj;
prj.CreateInstance(__uuidof(Project));
NodePtr node;
node.CreateInstance(__uuidof(Node));
prj->collection->Append((ContainerItem**)&node.GetInterfacePtr());

在 C++ 中这些类型的 COM 指针转换是否有特定的方法?我错过了什么?

【问题讨论】:

C 样式转换在 COM 接口上无效,您必须使用 QueryInterface()。 C# 自动完成,但您必须在 C++ 中自己完成。 Append 似乎不太可能将ContainerItem** 作为参数。那没有任何意义。 Append 的声明是什么? NodeContainerItem 之间有什么关系(如果有的话)? @IgorTandetnik 定义为Container::Append(ContainerItem**, long*),顺便说一下第二个参数可以为null。我不知道 Node 和 ContainerItem 之间的关系,因为它没有在编译器从 COM DLL 创建的 .tli 文件中表示。 【参考方案1】:

COM 转换是使用QueryInterface() 方法完成的。查询对象是否支持接口(基于 GUID),如果支持接口,则内部引用计数器递增(参见AddRef())并返回指向接口的指针。 MSDN has more detail on the inner workings.

C++ 不像 C# 那样直接支持“COM cast”的代码生成,但它的实现很简单。

struct bad_com_cast : std::runtime_error 
    bad_com_cast() : std::runtime_error("COM interface not supported") 
;

template <class To, class From>
To* qi_cast(From* iunknown)

    HRESULT hr  = S_OK;
    To* ptr = NULL;
    if (iunknown) 
        hr = iunknown->QueryInterface(__uuidof(To), (void**)(&ptr));
        if (hr != S_OK) 
            throw bad_com_cast(); // or return NULL
        
    
    return ptr;

使用上面的“cast”,示例可以如下实现;

ContainerItem* ci = qi_cast<ContainerItem>(node);
prj->collection->Append(&ci);

如果正在使用ATL库,可以直接使用ATL::CComQIPtr&lt;&gt;获取等价语义;

auto ci = CComQIPtr<ContainerItem>(node);
if (ci) 
    // ...

【讨论】:

【参考方案2】:

就像@HansPassant 评论的那样,我不得不使用 QueryInterface 函数:

ContainerItem* ci = nullptr;
node.QueryInterface(__uuidof(ContainerItem), ci);
prj->collection->Append(&ci);

【讨论】:

以上是关于在 C++ 中转换 COM 类型的主要内容,如果未能解决你的问题,请参考以下文章

C++ 数据类型转换

C++ 介绍⁽⁴⁾|C++ 类型转换

C++中 OOP相关的类型转换

C++从青铜到王者第二十四篇:C++的类型转换

C++ 类型转换

C++的类型转换