为什么对象明明支持接口却得到E_NOINTERFACE?

为什么对象明明支持接口却得到E_NOINTERFACE?

作者:BlogUpdater |  时间:2022-01-21 |  浏览:268 |  评论已关闭 条评论

解密时刻
经常有朋友问到这样一个问题:当我调用CoCreateInstance获取一个对象接口的时候,我明明知道,这个对象已经实现了我想要的接口,但是CoCreateInstance还是无情地返回了E_NOINTERFACE,这是怎么回事儿。

这个问题,实际上和”IMarshal接口丢失”是一样的问题,只不过你需要从另一个角度来看待。

如果你的线程模型和你准备创建的对象模型兼容,则COM库会尝试进行列集和散集(Marshalling)。如果这个Marshalling相关的接口不存在,则你就会得到E_NOINTERFACE这个错误,因为列集接口没有(丢失)了。

发生这个错误的最普遍的一个场景,是尝试在一个多线程套间(Multi-Threaded Apartment)中使用外壳提供的COM对象。请一定要记得,外壳提供的COM对象,大多数情况下都是套间线程(apartment-threaded),而不是自由线程(free-threaded)。如果你想使用这些对象,则你需要从一个单线程套间线程模型中来访问它们。

总结
对于列集(Marshal)的理解,确实需要一段时间。如果你不能理解它,就始终无法进入到COM的高玩世界。
通俗来说,当你需要在套间边界进行接口指针的传递的时候,直接传递原始指针是不行的,需要使用列(散)集技术来作为一个中转层进行两个套间之间的转换。
更深层次的东西,我也不是很懂了。十年过去了,COM一直是我心中的痛(兄弟我还是没整明白啊)。

最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《Why do I get E_NOINTERFACE when creating an object that supports that interface?》

最近我写了个东西
正如你们所知道的,拓扑梅尔智慧办公平台(Topomel Box)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。

评论已关闭。