【发布时间】: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 为我在非托管内存中创建的字符串吗?看起来这仍然存在当前实现的许多问题(它仍然可能需要删除或替换字符),所以我不确定这是否是一种改进。我还缺少另一种编组方法吗?
【问题讨论】: