【问题标题】:How to derive all offered interface types from an COM idl?如何从 COM idl 派生所有提供的接口类型?
【发布时间】:2019-07-15 16:44:46
【问题描述】:

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

我有一个关于类似于以下模式的几个接口的问题(我认为sn-p是自包含的):

[
  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”。

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

很明显

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

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

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

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

Q2:是否可以从 IDL 中获取 COM 属性的类型,如果可以,如何获取?

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

Q3:是否有 API 可用于查询可执行文件的 OLE 接口,是否提供额外的元数据?

感谢您的见解。

【问题讨论】:

  • 不是 C# 执行此操作,而是类型库导入器。 Tlbimp.exe 是独立工具,它生成的互操作库具有为它提供类似 C# 接口的管道。 Dispid -4 等效于 GetEnumerator(),Dispid 0 是它派生元素类型的索引器。 tlbimp 的托管版本已在 Codeplex 上发布,我认为它是 here now。它有点牛。

标签: c# com ole


【解决方案1】:

1) 因为 dispid 是一个众所周知的:DISPID_NEWENUM (-4),它指定了一个枚举数。项目的类型 (IVariable) 可以从使用 0 (DISPID_VALUE) 的 Item(索引器)成员推断出来。

DISPID_NEWENUM -4

这必须指定与一个关联的 DISPID _NewEnum 方法必须具有以下签名。

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

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

2) 是的,如果在 idl (duh) 中指定了属性类型,但在这里你看到的是一个纯后期绑定接口(仅限IDispatch),它是完全动态的,所以不,在这个案例。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-12
    • 2010-09-16
    • 2019-11-05
    • 2019-05-16
    • 2010-12-24
    • 2014-07-07
    相关资源
    最近更新 更多