Microsoft 游戏开发工具包中的 UTF-8 支持
本话题概述了 Microsoft 游戏开发工具包(GDK)中的 UTF-8 支持。
- 概述
- -A 与 -W API
- 主机代码页
- Windows 电脑代码页
- MultiByteToWideChar/WideCharToMultiByte
- 高级 UTF-8 的 ICU 和全球化支持
- 支持早期版本的 Windows
概述
UTF-8 是用于国际化的通用代码页,它通过使用 1–4 字节变量宽度编码来支持所有 Unicode 代码点。 它在网上广泛使用,一些竞争性平台(如基于 Unix 的系统)默认情况下在 UTF-8 下运行。 通过在 UTF-8 下运行,你只需最小的工作量和测试负担,就可确保国际方案的最大兼容性和数据互换。
Windows 本身在 UTF-16(或 WCHAR
)下运行,它需要使用 MultiByteToWideChar
和 WideCharToMultiByte
进行代码页转换。 这是 Windows 在编写针对多个平台的代码时的特有负担。 更大的挑战在于 Windows 的 ANSI 代码页概念,它在不同地区和不同用户配置中是不同的,错误地依赖它时可导致严重的不一致行为。
Microsoft 游戏开发工具包 (GDK) 和 Windows 正在努力推动支持 UTF-8 的工作,以消除 Windows 在针对多个平台和网站以及与它们互换时的代码转换问题。 这还将减少应用和游戏中的国际化问题,并且简化调试它们所需的测试矩阵。
-A 与 -W API
Win32 API 通常提供 -A 和 -W 变体。
-A 变体采用在系统上配置的 ANSI 代码页,用于处理 char*。
-W 变体在 UTF-16 下运行,用于处理 WCHAR
。
现在,-A API 已过时,因为 Windows 用了数十年时间来推广“Unicode”-W 变体。 不过,在最近的版本中,Windows 使用了 ANSI 代码页和 -A API,以便在新版 SKU 中引入 UTF-8 支持。 如果将 ANSI 代码页配置为 UTF-8,-A API 将在 UTF-8 下运行。 此模型的优势是支持使用 -A API 生成的现有代码,无需进行任何代码更改。
对于 Microsoft 游戏开发工具包 (GDK),UTF-8 是主机上默认的唯一的 ANSI 代码页。 主机上的 -A API 始终在 UTF-8 下运行,并且它是推荐调用的一组 API,用于实现最大程度的可移植性。 还提供 -W API 以实现源代码与现有 Windows 代码的兼容(可能来自被前推的游戏的现有 Windows 电脑版本)。
主机代码页
UTF-8 是主机上默认的唯一代码页,因此建议使用 -A API 来充分利用这一点。
Windows 电脑代码页
为了兼容,Windows 电脑上的默认 ANSI 代码页仍采用旧版(因区域和用户配置而异)。 这会增加面向 Windows 电脑和主机的用户的负担,他们必须考虑代码页转换以及调试时所需的测试矩阵问题。
为了缓解此问题,Windows 引入了一种强制进程选择 UTF-8 作为进程代码页的方式(无论系统代码页是什么)。 这可以通过使用 appxmanifest
(针对打包的应用)或 fusion manifest(针对设置了 ActiveCodePage
属性的非打包应用)来实现。 有关详细信息,请参阅以下代码示例。
注意
此功能仅适用于 Windows 19H1 或更高版本的内部版本。 你可以声明此属性,并面向/运行早期的 Windows 内部版本。 但必须按以往处理旧版代码页的检测和转换。 目标版本为 19H1 或更高版本时,进程代码页将始终为 UTF-8。
appxmanifest(已打包)
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="https://schemas.microsoft.com/appx/manifest/foundation/windows10"
...
xmlns:uap7="https://schemas.microsoft.com/appx/manifest/uap/windows10/7"
xmlns:uap8="https://schemas.microsoft.com/appx/manifest/uap/windows10/8"
...
IgnorableNamespaces="... uap7 uap8 ...">
<Applications>
<Application ...>
<uap7:Properties>
<uap8:ActiveCodePage>UTF-8</uap8:ActiveCodePage>
</uap7:Properties>
</Application>
</Applications>
</Package>
Win32 manifest(未打包)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity type="win32" name="..." version="6.0.0.0"/>
<application>
<windowsSettings>
<activeCodePage xmlns="https://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
</windowsSettings>
</application>
</assembly>
Note: You can add a manifest to an existing executable via the command line with mt.exe -manifest <MANIFEST> -outputresource:<EXE>;#1
MultiByteToWideChar/WideCharToMultiByte
使用 MultiByteToWideChar 和 WideCharToMultiByte 函数可以在 UTF-8 和 UTF-16 (WCHAR
)(以及其他代码页)之间转换。 如果旧版 Win32 API 只能理解 WCHAR
,这将特别有用。 使用这些函数可以将 UTF-8 输入转换为 WCHAR
以传入 -W API,然后根据需要将任何结果转换回去。
在 Microsoft 游戏开发工具包 (GDK) 中使用这些函数时,根据文档将 CodePage CP_UTF8
与 dwFlags
(为 0 或 MB_ERR_INVALID_CHARS
)一起使用。 否则你将收到错误 ERROR_INVALID_FLAGS
。
注意
在主机上, CP_ACP
始终与 CP_UTF8
相同。 如果显式切换到 CP_UTF8
不易实现,可以继续使用现有代码。 在 Windows 电脑上,仅当在 19H1+ 上运行且将上述 ActiveCodePage
属性设置为 UTF-8 时,CP_ACP
才等于 CP_UTF8
。 否则,它采用旧的系统代码页。 今后,最佳做法是显式使用 CP_UTF8
。
高级 UTF-8 的 ICU 和全球化支持
ICU 是 Unicode 库的国际组件。 它是开源、跨平台的国际化库,该库通过 C/C++ 接口支持高级 UTF-8 操作(例如排序规则、规范化和词汇切分)。
自版本 64.1 起,此库已针对 Microsoft 游戏开发工具包 (GDK) 进行了更新。 要使用它,请生成该库(请参阅自述文件中的 #HowToBuild),然后使用你的游戏将该库打包(请参阅自述文件中的 #HowToPackage)。
注意
自述文件不直接在 GitHub 上呈现。 如果你通过将存储库在本地克隆来生成,可以在本地查看它。
支持早期版本的 Windows
如果您针对的 Windows 版本低于 19H1(包括 Windows 7),则必须处理旧代码页检测和转换问题。
我们正在探索提供一个静态帮助程序库,该库提供 Win32 API 的 -Utf8 变体,无需执行代码页检测和转换。 这将提供面向主机和 Windows 电脑(向下涵盖到 Windows 7)的通用编程面。