为 COM 接口启用编组需要啥?

Posted

技术标签:

【中文标题】为 COM 接口启用编组需要啥?【英文标题】:What is required to enable marshaling for a COM interface?为 COM 接口启用编组需要什么? 【发布时间】:2010-10-25 13:09:03 【问题描述】:

我有一个没有类型库的 32 位 ATL COM 组件。它为一个给定的类提供了一个类工厂,该类实现了多个接口。

当我将它用作进程内服务器时,一切正常 - 客户端调用 CoCreateInstance(),对象被实例化,QueryInterface() 检索指向所请求接口的指针。但是当我将组件放入 COM+ 时,我无法再实例化该类 - CoCreateInstance() 现在返回 E_NOINTERFACE。

我认为问题在于 COM+ 无法执行封送处理,因为没有类型库 - 它不知道该怎么做。我需要生成并注册一个类型库来解决这个问题还是有其他方法?

【问题讨论】:

ATL 项目向导通常设置有一个类型库,作为资源嵌入到项目输出中并注册到 coclass。 是的,我知道。问题是我实现了一个微软已经定义的接口,没有提供 idl 文件或类型库。这就是为什么我很难重新发明充满自定义类型的类型库。 fyi,它在 COM 的上下文中是“编组”,在 Java 的上下文中是“编组”。 :-) 【参考方案1】:

类型库是支持编组的一种方式,代理/存根 DLL(从 IDL 生成)是另一种方式。但是,在这两种情况下,您首先都需要 IDL。

如果微软没有为此接口提供 typelib/proxy DLL 或 IDL,那么可能是有原因的:可能接口使用了不可编组的数据结构,需要函数指针作为方法参数或其他东西传递像这样?如果是这种情况,则无法使此接口适用于 DCOM。

也许您可以重建 IDL,但很有可能,它只是不可行。然后你最后的后备可能是使用自定义或处理程序编组,但这可能不值得付出努力。也就是说,我建议考虑其他不涉及使用 DCOM 接口的路由,这些接口不是为 DCOM 设计的。

【讨论】:

【参考方案2】:

要使 COM 接口可以使用 Microsoft 的默认编组器进行编组,该接口必须在其标头中定义 DUAL 或 OLEAUTOMATION 属性。

如果定义的方法的参数是接口指针,则相同的要求扩展到这些接口。

另外,接口名称必须出现在定义它的 IDL 的 LIBRARY 部分中。这也扩展到其他引用的接口。

如果不满足这些条件,接口将无法编组。

【讨论】:

【参考方案3】:

乌尔克。我建议您在microsoft.public.vc.atl 上提问,因为我认为您会在那里找到更多专家。我认为(尽管我不是专家)这个问题与 COM+ 的关系不如注册代理/存根的问题。 (换句话说,即使您编写了自己的 COM 客户端以在进程外访问您的组件,您也可能会遇到同样的问题)如果您有标准的自动化兼容接口,那么 Windows 就知道如何编组您的对象美好的。但否则它会感到困惑。

如果没有类型库,您要么需要注册代理/存根,要么需要自己实现 IMarshal 来处理自定义封送处理。 (或者还有这个我不明白的“处理程序编组”的东西)

您关于为什么没有类型库的评论(实现了微软已经定义的接口,但没有类型库)向我提出了一个危险信号。你能提供更多细节吗?如果它在 .DLL 或 .EXE 中,但类型信息在库本身内部(而不是外部 .TLB 文件),则可能提取正确的信息以使一切正常,我只是不熟悉过程。

(作为记录,我已经放弃了 ATL/COM 编程,转而使用 Java,所以虽然我可以让你知道我过去记得的东西,但我现在不使用这些工具,这对我来说会很困难回到他们那里提供更多帮助。但是 microsoft.public.vc.atl 上的人非常聪明。)

【讨论】:

如果 ATL usenet 组提供任何帮助,请在此处概括信息。 我在微软SDK的更高版本中找到了.idl文件。我可以将它包含在项目中,这将解决问题。但是由于多种自定义类型,该接口与自动化不兼容。所以我介绍了我自己的可以愉快地编组的接口,并创建了一个前端组件来实现原始接口和对我的组件的隧道调用。这样它通过 COM+ 工作,我现在只需要为前端创建一个 64 位版本,而不是为内部组件所依赖的所有东西。

以上是关于为 COM 接口启用编组需要啥?的主要内容,如果未能解决你的问题,请参考以下文章

创建 COM 接口,返回一个在 C# 中编组为 IntPtr 的指针

将 COM 接口编组到多个线程时,克隆流是不是足够,还是需要复制?

Azure 无法将事务编组为弹性事务的传播令牌(适用于 MSDTC)

如何手动将 .NET 对象编组为双 COM 接口?

在three.js中,我们啥时候需要启用PointCloud.sortParticles?

是啥导致我尝试为 AWS-EB 启用 SSH 失败?