调用了错误的重载方法
我用C#编写了COM组件。接口方法按以下方式声明:
[ComImport,
Guid("7D37EE00-143E-40DF-B177-BF091D7CD36A"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMonogramServiceHost
{
void Send(
[In, MarshalAs(UnmanagedType.BStr)] string text);
void Send([In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]byte[] data,
[In, MarshalAs(UnmanagedType.I4)] int length);
}
这些方法从 C++ 代码中调用。在 C++ 中声明的相同接口是:
DECLARE_INTERFACE_(IMonogramServiceHost, IUnknown)
{
STDMETHOD(Send)(BSTR text);
STDMETHOD(Send)(uint8 *buf, int length);
};
我正在调用第二个方法。它的参数只是无符号字符数组,其长度由参数“length”定义。由于某些未知原因,代码进入方法“void Send(string text)”。从 COM 方法返回后,调试器显示以下错误消息:
运行时检查失败 #0 - ESP 的值未在函数调用中正确保存。这通常是用一种调用约定声明的函数和用另一种调用约定声明的函数指针调用的结果。
当我将方法重命名为 ASend 时,会调用正确的版本。为什么会发生这种情况?我看不出这有什么逻辑。
I have written COM component in C#. Interface methods are declared in following manner:
[ComImport,
Guid("7D37EE00-143E-40DF-B177-BF091D7CD36A"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMonogramServiceHost
{
void Send(
[In, MarshalAs(UnmanagedType.BStr)] string text);
void Send([In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]byte[] data,
[In, MarshalAs(UnmanagedType.I4)] int length);
}
These methods are called from C++ code. This same interface declared in C++ is:
DECLARE_INTERFACE_(IMonogramServiceHost, IUnknown)
{
STDMETHOD(Send)(BSTR text);
STDMETHOD(Send)(uint8 *buf, int length);
};
I am calling second method. Its parameter is simply unsigned char array whose length is defined by parameter 'length'. By some unknown reason code steps into method 'void Send(string text)'. After returning from COM method debugger displays following error message:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
When I rename method to ASend correct version is called. Why is this happening? I dont see logic in this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
COM 不支持函数重载。目前尚不清楚您如何进行调用,但后期绑定肯定会失败。当请求“发送”时,IDispatch::GetIDsOfNames() 将返回错误的 dispid。在本例中没有强烈表明这一点,因为您是从 IUnknown 派生的。但其本身就有足够的理由给这些方法赋予不同的名称。
我建议使用 SendText 与 SendBytes。字节和字符在 Unicode 中根本不等同,这本身就很合理。
COM doesn't support function overloading. It isn't that clear how you are making the call, but late binding will certainly fail. IDispatch::GetIDsOfNames() is going to return the wrong dispid when asked for "Send". That's not strongly indicated in this case since you derive from IUnknown. But in itself is enough reasons to give these methods distinct names.
I'd suggest SendText vs SendBytes. Quite justified in itself, bytes and characters are not at all equivalent in Unicode.
C# char 数组是 C++ uint16 数组,而不是 uint8 数组。第二个签名不匹配。
A C# char array is a C++ uint16 array, not a uint8 array. The second signature is a mismatch.