COM 是如何工作的?

How does COM work?

我有一个据称是 COM 对象的 dll。我试图了解当 dll 中没有可用的导出函数时,CLR 究竟是如何确定要调用哪个函数的(我使用 depends 进行了检查)。

  [Guid("DEADBEEF....")]
  [TypeLibType(...)]
  [ComImport]
  public interface ISomething
  {
    [DispId(1)]
    [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
    [return: MarshalAs(UnmanagedType.IDispatch)]
    object DoSomething([MarshalAs(UnmanagedType.IDispatch), In] object something);

}

在这里我检查了 MSIL,没有关于它位于什么地址或函数名称或偏移量的信息。

此外,似乎没有关于对象是如何布局的信息,因此它的 vtable 指针是如何传递的,等等。

这是什么魔法?

在(非托管)代码中,可以在与 COM 对象关联的 "type library" 文件上使用 LoadTypeLib/LoadTypeLibEx。很常见的是,这是为 COM 对象本身注册的 EXE 或 DLL(但它也可以是独立的 TLB 文件、外部类型库等)。 LoadTypeLib 的文档在 https://msdn.microsoft.com/en-us/library/windows/desktop/ms221027(v=vs.85).aspx.

处有进一步的指示

获得 ITypeLib/ITypeLib2 类型库接口后,它会提供所有 COM 对象信息,包括接口、vtable 布局、原型等。完整文档位于 https://msdn.microsoft.com/en-us/library/windows/desktop/ms221549(v=vs.85).aspx.

大多数 Visual Studio 版本都提供了 OLE/COM 对象查看器,这是 LoadTypeLib 的一个实际应用示例,它基本上可以将给定的类型库反编译回 IDL。我不能 post 超过 2 个 URL,但查找 https-//msdn.microsoft.com/en-us/library/d0kh9f4c.aspx.

在托管代码中,编译器透明地导入类型库,尽管在幕后它所做的工作与 OLE/COM 查看器基本相同,此外还添加了必要的托管包装器。有关详细信息,请参阅 https-//msdn.microsoft.com/en-us/library/xwzy44e4(v=vs.110).aspx。