【问题标题】:How do I PInvoke a multi-byte ANSI string?如何 PInvoke 多字节 ANSI 字符串?
【发布时间】:2009-04-30 17:37:17
【问题描述】:

我正在为不支持 Unicode 字符串但支持多字节 ANSI 字符串的库开发 PInvoke 包装器。在调查有关库的 FxCop 报告时,我注意到正在使用的字符串封送处理有一些有趣的副作用。 PInvoke 方法使用“最佳匹配”映射来创建单字节 ANSI 字符串。为了说明,这是一种方法的样子:

[DllImport("thedll.dll", CharSet=CharSet.Ansi)]
public static extern int CreateNewResource(string resourceName);

使用包含非 ASCII 字符的字符串调用此函数的结果是 Windows 找到一个“关闭”字符,通常这看起来像它最终是“???”。如果我们假设 'a' 是一个非 ASCII 字符,那么将“cat”作为参数传递将创建一个名为“c?t”的资源。

如果我遵循 FxCop 规则中的指导方针,我最终会得到如下结果:

[DllImport("thedll.dll", CharSet=CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern int CreateNewResource([MarshalAs(UnmanagedType.LPStr)] string resourceName);

这引入了行为上的改变;现在,当无法映射字符时,将引发异常。这让我很担心,因为这是一个重大变化,所以我想尝试将字符串编组为多字节 ANSI,但我看不到这样做的方法。 UnmanagedType.LPStr 指定为单字节 ANSI 字符串,LPTStr will be Unicode or ANSI depending on the system, and LPWStr is not what the library expects.

如何告诉 PInvoke 将字符串编组为多字节字符串?我看到有一个WideCharToMultiByte() API 函数,我可以将签名更改为期望 IntPtr 为我在非托管内存中创建的字符串吗?看起来这仍然存在当前实现的许多问题(它仍然可能需要删除或替换字符),所以我不确定这是否是一种改进。我还缺少另一种编组方法吗?

【问题讨论】:

    标签: string pinvoke


    【解决方案1】:

    ANSI 多字节,ANSI 字符串根据系统当前启用的代码页进行编码。 WideCharToMultiByte 的工作方式与 P/Invoke 相同。

    也许您所追求的是转换为 UTF-8。尽管WideCharToMultiByte 支持这一点,但我认为 P/Invoke 不支持,因为不可能采用 UTF-8 作为系统范围的 ANSI 代码页。此时,您将考虑将字符串作为IntPtr 传递,尽管如果您这样做,您也可以使用托管Encoding 类进行转换,而不是WideCharToMultiByte

    【讨论】:

    • 我看你是对的;我一直在使用当前代码页之外的字符进行测试,并且想不出任何可以在我的代码页中实际工作的多字节字符。我正在摸索,试图找到一个代码页/字符组合,我可以将它扔给函数以获得一些信心,但我认为你是对的。
    • 我想出了如何测试它:我使用了我们拥有的日语本地化 XP 的图像,并设置了一些名称由大量日语字符组成的资源。这在日本机器上效果很好,但在英文机器上却惨遭失败。我希望 like 的事情表现得好像我在使用 Unicode,但是从你的解释和我的实验中,我发现这是不可能的,而且我已经尽可能接近它了.我只需要等待库的维护人员实现 Unicode 支持。
    【解决方案2】:

    这是我发现完成此任务的最佳方法。不是编组为字符串,而是编组为字节 []。让 pinvoke 函数 API 的调用者负责以最合适的方式转换为字节数组。最有可能使用 Text.Encoding 类之一。

    【讨论】:

      【解决方案3】:

      如果您最终不得不手动调用 WideCharToMultiByte,我将摆脱 p/invoke 并在 C++/CLI 包装函数中使用 WideCharToMultiByte 手动编组它。在这些互操作场景中,托管 C++ 比 C# 要好得多。

      不过,如果这是您唯一的 p/invoke,那可能就不值得了。

      【讨论】:

      • 既然有 C# 的解决方案,为什么还要建议使用不同的语言?
      猜你喜欢
      • 2013-02-05
      • 2013-08-21
      • 1970-01-01
      • 2011-03-22
      • 1970-01-01
      • 2010-12-31
      • 1970-01-01
      • 2010-10-23
      • 2014-07-12
      相关资源
      最近更新 更多