问题描述
RimeSharp 同时支持 net8.0 和 net472,但在 Windows 上使用 net472 运行时,从 librime 返回的部分 UTF-8 字符串会出现乱码。
相同代码在 net8.0 下输出正常。
复现方式
我将 RimeSharp.Test 修改为同时目标到:
<TargetFrameworks>net8.0;net472</TargetFrameworks>
同时显式将控制台输入输出设置为无 BOM 的 UTF-8,以排除终端编码的影响:
Console.InputEncoding = new System.Text.UTF8Encoding(false);
Console.OutputEncoding = new System.Text.UTF8Encoding(false);
分别运行:
dotnet run --project RimeSharp.Test --framework net8.0
dotnet run --project RimeSharp.Test --framework net472
测试使用 luna_pinyin,输入:
实际结果
net8.0 输出正常:
schema: luna_pinyin / 朙月拼音
status: composing
[ni hao]|
page: 1 (of size 5)
. [你好]
. 妳好
. 逆號
. 你
. 擬
schema list:
1. luna_pinyin [朙月拼音]
2. cangjie5 [倉頡五代]
current schema: [luna_pinyin]
net472 中对应字符串损坏:
schema: �� / � ��
status: composing
[ࡪ�
page: 1 (of size 5)
. []
. p���
. p���
. ��
. ࢪ�
schema list:
1. `�� [�
��]
2.
�� [ :��]
current schema: [luna_pinyin]
librime 初始化、部署、会话创建以及布尔状态均能正常工作,问题集中在从原生结构体返回的字符串字段。
初步分析
乱码字段都使用了结构体字段自动编组:
[MarshalAs(UnmanagedType.LPUTF8Str)]
public string? SchemaName;
目前确认受影响的字段包括:
RimeStatus.SchemaId
RimeStatus.SchemaName
RimeComposition.Preedit
RimeCandidate.Text
RimeCandidate.Comment
RimeSchemaListItem.SchemaId
RimeSchemaListItem.Name
这表明问题可能来自 .NET Framework 4.7.2 对结构体内 LPUTF8Str 字段的编组行为,而不是 PowerShell 或控制台编码。
可能的修复方式是将原生返回结构体中的字符串字段声明为 IntPtr,并通过现有的 UTF8Marshal.PtrToStringUTF8() 显式转换,同时保持原生结构体的字段顺序和 ABI 布局不变。
附件
附带的 rimesharp-test-net472.patch 仅用于让 RimeSharp.Test 同时运行于 net8.0 和 net472,方便复现和对照;该 patch 尚未修复核心库中的 UTF-8 编组问题。
rimesharp-test-net472.patch
问题描述
RimeSharp同时支持net8.0和net472,但在 Windows 上使用net472运行时,从 librime 返回的部分 UTF-8 字符串会出现乱码。相同代码在
net8.0下输出正常。复现方式
我将
RimeSharp.Test修改为同时目标到:同时显式将控制台输入输出设置为无 BOM 的 UTF-8,以排除终端编码的影响:
分别运行:
测试使用
luna_pinyin,输入:实际结果
net8.0输出正常:net472中对应字符串损坏:librime 初始化、部署、会话创建以及布尔状态均能正常工作,问题集中在从原生结构体返回的字符串字段。
初步分析
乱码字段都使用了结构体字段自动编组:
目前确认受影响的字段包括:
RimeStatus.SchemaIdRimeStatus.SchemaNameRimeComposition.PreeditRimeCandidate.TextRimeCandidate.CommentRimeSchemaListItem.SchemaIdRimeSchemaListItem.Name这表明问题可能来自 .NET Framework 4.7.2 对结构体内
LPUTF8Str字段的编组行为,而不是 PowerShell 或控制台编码。可能的修复方式是将原生返回结构体中的字符串字段声明为
IntPtr,并通过现有的UTF8Marshal.PtrToStringUTF8()显式转换,同时保持原生结构体的字段顺序和 ABI 布局不变。附件
附带的
rimesharp-test-net472.patch仅用于让RimeSharp.Test同时运行于net8.0和net472,方便复现和对照;该 patch 尚未修复核心库中的 UTF-8 编组问题。rimesharp-test-net472.patch