DllImport - ANSI与Uni​​code

Kas*_*sen 4 c# pinvoke

我对下面的测试问题的可能答案有一些疑问:

问题:您编写以下代码段以使用平台调用从Win32应用程序编程接口(API)调用函数.

string personName = "N?el";
string msg = "Welcome" + personName + "to club"!";
bool rc = User32API.MessageBox(0, msg, personName, 0);
Run Code Online (Sandbox Code Playgroud)

您需要定义一个最佳编组字符串数据的方法原型.您应该使用哪个代码段?

// A.
[DllImport("user32", CharSet = CharSet.Ansi)]
public static extern bool MessageBox(int hWnd, string text, string caption, uint type);
}

// B.
[DllImport("user32", EntryPoint = "MessageBoxA", CharSet = CharSet.Ansi)]
public static extern bool MessageBox(int hWnd,
[MarshalAs(UnmanagedType.LPWStr)]string text,
[MarshalAs(UnmanagedType.LPWStr)]string caption, uint type);
}

// C. - Correct answer
[DllImport("user32", CharSet = CharSet.Unicode)]
public static extern bool MessageBox(int hWnd, string text, string caption, uint type);
}

// D.
[DllImport("user32", EntryPoint = "MessageBoxA", CharSet = CharSet.Unicode)]
public static extern bool MessageBox(int hWnd,
[MarshalAs(UnmanagedType.LPWStr)]string text,
[MarshalAs(UnmanagedType.LPWStr)]string caption,
uint type);
}
Run Code Online (Sandbox Code Playgroud)

为什么正确的答案是C?不可能它也是A?唯一的区别是它将是ANSI而不是Unicode.

我知道它不能是D,因为我们选择Unicode作为字符集,然后使用ANSI函数作为入口点.

B为什么不工作?

Han*_*ant 10

 string personName = "N?el";
Run Code Online (Sandbox Code Playgroud)

这个字符串被这个问题所询问的确切问题弄乱了.毫无疑问,原版中看起来像这样:

 string personName = "Nöel";
Run Code Online (Sandbox Code Playgroud)

ö往往是一个问题,它的字符代码不是ASCII字符集,默认系统代码页可能不支持.这是当你pinvoke ANSI版本的MessageBox,也就是MessageBoxA时使用的.真正的函数是MessageBoxW,它采用utf-16编码的Unicode字符串.

MessageBoxA是旧版Windows中使用的遗留函数,早在程序仍然使用8位字符串时.它还没有完全消失,许多C和C++程序仍然倾向于使用8位编码.MessagBoxA通过将8位编码字符串转换为Unicode然后调用MessageBoxW来实现.如果您首先使用Unicode字符串,则速度慢且有损.

所以评价4个版本:

答:使用MessageBoxA + 8位编码,有风险.
B:使用MessageBoxA + Unicode,失败.
C:使用MessageBoxW + Unicode,好
D:使用MessageBoxA + Unicode,失败.

  • 由于MarshalAs属性,选项B是Unicode (3认同)