在 C++ 中转换 COM 类型
Casting COM types in C++
我有以下 COM 类型:Project
、ContainerItem
和 Node
。
Project
有一个集合 属性,带有一个接受 ContainerItem
的 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 指针?我错过了什么?
就像@HansPassant 评论的那样,我必须使用 QueryInterface 函数:
ContainerItem* ci = nullptr;
node.QueryInterface(__uuidof(ContainerItem), ci);
prj->collection->Append(&ci);
COM 转换是使用 QueryInterface()
method. The object is queried for its support of the interface (based on the GUID), and if the interface is supported, the internal reference counter is incremented (see AddRef()
) and a pointer to the interface is returned. 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<>
得到等价的语义;
auto ci = CComQIPtr<ContainerItem>(node);
if (ci) {
// ...
}
我有以下 COM 类型:Project
、ContainerItem
和 Node
。
Project
有一个集合 属性,带有一个接受 ContainerItem
的 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 指针?我错过了什么?
就像@HansPassant 评论的那样,我必须使用 QueryInterface 函数:
ContainerItem* ci = nullptr;
node.QueryInterface(__uuidof(ContainerItem), ci);
prj->collection->Append(&ci);
COM 转换是使用 QueryInterface()
method. The object is queried for its support of the interface (based on the GUID), and if the interface is supported, the internal reference counter is incremented (see AddRef()
) and a pointer to the interface is returned. 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<>
得到等价的语义;
auto ci = CComQIPtr<ContainerItem>(node);
if (ci) {
// ...
}