Skip to content

UTF-8 strings are corrupted on .NET Framework 4.7.2 #3

Description

@amorphobia

问题描述

RimeSharp 同时支持 net8.0net472,但在 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,输入:

nihao
print schema list

实际结果

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.0net472,方便复现和对照;该 patch 尚未修复核心库中的 UTF-8 编组问题。

rimesharp-test-net472.patch

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions