代码之家  ›  专栏  ›  技术社区  ›  HS.

Com声明的互操作顺序

  •  0
  • HS.  · 技术社区  · 16 年前

    [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,该IntPtr可以被转换成一个字符串,而这个字符串恰好包含了第一个开始的参数。

    我认为这与声明的顺序有关,尽管上面的声明是我在任何地方都见过的规范性声明。

    另外,我发现如果在Terminate的定义中添加任意IntPtr参数,则如下所示:

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

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

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

    2 回复  |  直到 16 年前
        1
  •  1
  •   arul    16 年前

    确保调度ID( dispid )通过比较生成的可调用包装器和IDL文件来正确设置。

        2
  •  1
  •   Hans Passant    16 年前

    你忘了3个未知的方法。IInternetProtocolRoot::Start()是vtable中的第四个方法。