【问题标题】:Com Interop Order of DeclarationsCom Interop 声明顺序
【发布时间】:2010-01-11 11:59:44
【问题描述】:

我有一个这样的接口声明:

[ComImport]
[Guid("79EAC9E4-BAF9-11CE-8C82-00AA004BA90B")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IInternetProtocol {
    //IInternetProtcolRoot
    void Start(
        [ MarshalAs(UnmanagedType.LPWStr) ] string szURL, 
        IInternetProtocolSink Sink, 
        IInternetBindInfo pOIBindInfo, 
        UInt32 grfPI, 
        UInt32 dwReserved);
    void Continue(ref _tagPROTOCOLDATA pProtocolData);
    void Abort(Int32 hrReason, UInt32 dwOptions);
    void Terminate(UInt32 dwOptions);
    void Suspend();
    void Resume();
    //IInternetProtocol
    [PreserveSig()] UInt32 Read(IntPtr pv, UInt32 cb, out UInt32 pcbRead);
    void Seek(_LARGE_INTEGER dlibMove, UInt32 dwOrigin, out _ULARGE_INTEGER plibNewPosition);
    void LockRequest(UInt32 dwOptions);
    void UnlockRequest();
}

实现此接口的对象应该调用Start 方法。然而,这并没有发生。但奇怪的是,我发现调用的是 Terminate 方法,如果我在 Terminate 方法上设置断点,然后查看 dwOptions 参数,它实际上包含一个可以转换为字符串的 IntPtr - 这恰好包含 Start 的第一个参数。

我认为这与声明的顺序有关,尽管上面的声明是我在各处看到的规范声明。

另外,我发现如果我在 Terminate 的定义中添加任意 IntPtr 参数,它看起来像这样:

Terminate(IntPtr a1, IntPtr a2, IntPtr a3, IntPtr a4, IntPtr a5, IntPtr a6)

该方法仍被成功调用,该字符串作为 a1 中的指针,其他字段填充有 13 0 或其他内存地址。

知道这里发生了什么吗? Start 方法只需要 5 个参数。然而在这里,我已经用 6 声明了 Terminate,它仍然在预期调用 Start 的地方被调用。

【问题讨论】:

    标签: c# com-interop


    【解决方案1】:

    通过将生成的可调用包装器与 IDL 文件进行比较,确保调度 ID (dispid) 设置正确。

    【讨论】:

      【解决方案2】:

      您忘记了 3 个 IUnknown 方法。 IInternetProtocolRoot::Start() 是 vtable 中的第四个方法。

      【讨论】:

      • 有趣。但是我在这里读到msdn.microsoft.com/en-us/library/aa645736(VS.71).aspx 你没有在声明中包含 IUnknown 和 IDispatch 成员。我很确定我在这里做错了什么......
      • 那篇文章讨论了 CLR 中内置的标准 COM 互操作支持。您似乎在使用 [ComImport] 做自己的事情。
      猜你喜欢
      • 2013-08-18
      • 1970-01-01
      • 2011-10-12
      • 2016-03-20
      • 1970-01-01
      • 1970-01-01
      • 2010-10-25
      • 2015-07-12
      • 2021-10-08
      相关资源
      最近更新 更多