【问题标题】:Wrong overload method called调用了错误的重载方法
【发布时间】:2011-02-02 12:31:28
【问题描述】:

我用 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);
};

我正在调用第二种方法。它的参数是简单的无符号字符数组,其长度由参数“长度”定义。通过一些未知的原因代码步入方法“无效发送(字符串文本)”。从 COM 方法调试器返回后显示以下错误消息:

运行时检查失败 #0 - ESP 的值未在函数调用中正确保存。这通常是用一个调用约定声明的函数和一个用不同调用约定声明的函数指针调用的结果。

当我将方法重命名为 ASend 时,会调用正确的版本。为什么会这样?我看不出这其中的逻辑。

【问题讨论】:

    标签: c# marshalling overloading


    【解决方案1】:

    COM 不支持函数重载。目前尚不清楚您是如何进行调用的,但是后期绑定肯定会失败。当要求“发送”时,IDispatch::GetIDsOfNames() 将返回错误的 dispid。由于您从 IUnknown 派生,因此在这种情况下并未强烈表明这一点。但其本身就足以为这些方法赋予不同的名称。

    我建议使用 SendText 与 SendBytes。这本身就很合理,字节和字符在 Unicode 中根本不等价。

    【讨论】:

      【解决方案2】:

      C# char 数组是 C++ uint16 数组,而不是 uint8 数组。第二个签名不匹配。

      【讨论】:

      • 我不需要传递 unicode 字符串,只需缓冲任意数据即可。对于 unicode 字符串,我使用第一种方法。
      • 而且我没有使用 char 数组,而是 8 位宽的字节数组。
      猜你喜欢
      • 1970-01-01
      • 2011-02-06
      • 1970-01-01
      • 2014-12-15
      • 1970-01-01
      • 2010-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多