c# - 在 C++ 中转换 COM 类型

标签 c# c++ com

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

在 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 指针?我错过了什么?

最佳答案

COM 转换是使用 QueryInterface() 完成的方法。查询对象是否支持该接口(interface)(基于 GUID),如果支持该接口(interface),则增加内部引用计数器(请参阅 AddRef())并返回指向该接口(interface)的指针。 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) {
    // ...
}

关于c# - 在 C++ 中转换 COM 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38570312/

相关文章:

c# - oracle c# 如何用like绑定(bind)变量

c# - JetBrains Rider 带着 watch 运行

c++ - 二进制 '*' : no global operator found which takes type 'statistician' (or there is no acceptable conversion)

c++ - c++中的模板类和friend关键字(具体例子引用boost::multi_index)

c# - 我可以将带有 C 风格方法的 C++ 接口(interface)导出到 C# dll 吗

c# - 使用 COM 接口(interface)时出现 System.InvalidCastException

c# - C#XmlSerializer会忽略xs:string以外的类型的xs:attribute

C# : the close method of Xml. 加载(文件)

C++ 修饰 basic_stream::underflow()

c++ - 关于 COM Release() 方法的问题