Com Interop 声明顺序
我有一个这样的接口声明:
[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 声明了 Terminate,但它仍然在预期调用 Start 的地方被调用。
I have an interface declaration like this:
[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();
}
The object that implements this interface is supposed to have it's Start
method called. However, that is not happening. But curiously, I find that the Terminate method is being called instead, and if I set a break point on the Terminate method, and then look at the dwOptions parameter, it actually contains an IntPtr which can be cast into a string - which happens to contain what would be first parameter to Start.
I assume this has something to do with the order of declaration, even though the above declaration is the canonical one I've seen everywhere.
Also, I find that if I add arbitrary IntPtr arguments to the definition of Terminate so it looks like this:
Terminate(IntPtr a1, IntPtr a2, IntPtr a3, IntPtr a4, IntPtr a5, IntPtr a6)
the method is still successfully being called with the string as a pointer in a1 and other fields being populated with either 13
0
or what looks like another memory address.
Any idea what's going on here? The Start method only takes 5 parameters. Yet here, I've declared Terminate with 6 and its still being called in the place where Start is expected to be called.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
通过将生成的可调用包装器与 IDL 文件进行比较,确保调度 ID (
dispid
) 设置正确。Make sure that the dispatch ids (
dispid
) are set correctly by comparing the generated callable wrapper with the IDL file.你忘记了 3 个 IUnknown 方法。 IInternetProtocolRoot::Start() 是 vtable 中的第四个方法。
You forgot the 3 IUnknown methods. IInternetProtocolRoot::Start() is the 4th method in the vtable.