我有这样的接口声明:
[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的第一个参数。
我认为这与声明的顺序有关,即使上述声明是我在任何地方都看到的规范声明。
另外,我发现如果我将任意IntPtr参数添加到Terminate的定义中,那么它看起来像这样:
Terminate(IntPtr a1, IntPtr a2, IntPtr a3, IntPtr a4, IntPtr a5, IntPtr a6)
该方法仍然成功调用,字符串作为a1中的指针,其他字段填充了13
0
或看起来像另一个内存地址。
知道这里发生了什么吗? Start方法只需要5个参数。然而,在这里,我已经宣布终止为6,并且仍然会在预计将调用Start的地方调用它。
答案 0 :(得分:1)
通过将生成的可调用包装器与IDL文件进行比较,确保正确设置了调度ID(dispid
)。
答案 1 :(得分:1)
你忘记了3个IUnknown方法。 IInternetProtocolRoot :: Start()是vtable中的第4个方法。