如何从 COM idl 派生所有提供的接口类型?

How to derive all offered interface types from an COM idl?

我的目标是生成允许在 Java 中调用 COM 接口的桥接代码。我确实成功地使用了 JNA,因为我获得了接口的句柄并且可以成功地使用接口的大部分功能。

我对几个类似于以下模式的接口有疑问(我认为该片段是独立的):

[
  odl,
  uuid(4D27AA78-B622-42E7-A237-3DA76B14A23D),
  helpstring("IVariables Interface"),
  dual,
  oleautomation
]
interface IVariables : IDispatch {
    [id(0x00000001), propget, helpstring("property Application")]
    HRESULT Application([out, retval] IDispatch** pVal);
    [id(0x00000002), propget, helpstring("property Parent")]
    HRESULT Parent([out, retval] IDispatch** pVal);
    [id(0x00000003), propget, helpstring("property Count")]
    HRESULT Count([out, retval] long* pnCount);
    [id(00000000), propget, helpstring("property Item")]
    HRESULT Item(
                    [in] VARIANT index, 
                    [out, retval] IVariable** pVal);
    [id(0xfffffffc), propget, helpstring("property _NewEnum")]
    HRESULT _NewEnum([out, retval] IUnknown** ppEnum);
    [id(0x00000004), helpstring("method Add")]
    HRESULT Add(
                    [in] BSTR Name, 
                    [in, optional] VARIANT Value, 
                    [out, retval] IVariable** pVal);
    [id(0x00000005), helpstring("method Remove")]
    HRESULT Remove([in] VARIANT index);
};

如果将此接口导入 Visual Studio 并在 C# 项目中使用,则 C# 会检测到上面实现了接口 IEnumerator 并允许迭代元素。此外,C# 甚至知道迭代类型,即 'IVariable'.

问题 1:C# 或其 COM 接口导入器如何得出上述 'IVariables' 实现 'IEnumerator' 且枚举元素为 'IVariable' 类型的结论?

显然是行

[id(0xfffffffc), propget, helpstring("property _NewEnum")]

必须做到这一点。但是,虽然我在其他 IDL 中发现了相同的构造,但我在 Google 中找不到对此的任何解释。可能相关的是我没有从 IDL 中获得任何关于属性类型的信息,请参阅

    [id(0x00000002), propget, helpstring("property Parent")]

在上面的 IDL 中。既没有类型 'Parent' 也没有类型 'IParent'。因此:

问题 2:是否可以从其 IDL 中导出 COM 属性 的类型,如果可以,如何导出?

最后,将上述类型导入C#时,实际上并没有使用上述IDL。相反,导入程序期望支持 OLE 的应用程序的可执行文件读取其类型库(类似于 Microsoft oleview.exe 工具)。这引出了我的最后一个问题:

问题 3:是否有 API 可用于查询可执行文件的 OLE 接口并且它是否提供额外的元数据?

感谢您的见解。

1) 因为 dispid 是众所周知的:DISPID_NEWENUM (-4) 指定枚举器。项目的类型 (IVariable) 可以从使用 0 (DISPID_VALUE).

Item(索引器)成员推导出来

DISPID_NEWENUM -4

This MUST designate the DISPID associated with a _NewEnum method that MUST have the following signature.

HRESULT _NewEnum([out,retval] IEnumVARIANT** ppenum);

or

HRESULT _NewEnum([out,retval] IUnknown** ppenum);

2) 是的,如果在 idl 中指定了 属性 类型(废话),但这里您看到的是纯后期绑定接口(仅 IDispatch),它是完全动态,所以不,在这种情况下。

3) .IDL 未被使用,因为 .TLB 格式是等效的,并且可以通过 ITypeLib 等进行编程。只有 MIDL 编译器使用 IDL。在运行时,一般情况下可用的 TLB 不多。最简单形式的 COM 基本上只需要 IUnknown,仅此而已。