首页 > 解决方案 > 在 WinRT 上使用字符串编组结构

问题描述

我正在开发一个桌面应用程序的精简版 Windows IoT Core ARM 端口,作为概念证明,用于单板计算机的更多分发选项(目前使用 Raspberry Pi3 B+)。我们需要编组一个由空终止字符串对组成的非托管 C 数组,如下所示:

// The C struct
typedef struct {
const char *key;
char* value;
} Pair;

// Its managed counterpart
[StructLayout(LayoutKind.Sequential)]
public struct Pair
{
    [MarshalAs(UnmanagedType.LPStr)]
    public string Key;
    [MarshalAs(UnmanagedType.LPStr)]
    public string Value;
}

当前在我们的 WPF 和 Forms 应用程序上工作的以下 PInvoke 留下了指向 info 中的数据和 infoLength 中的元素数量的指针:

[DllImport("path/to.dll", EntryPoint = "unmanagedfunction", CallingConvention = CallingConvention.Cdecl)]
public static extern OperationResultEnum GetDeviceInfo(IntPtr session, out IntPtr info, out int infoLength);

然后我们使用以下通用函数对其进行编组:

public static T[] GetArray(IntPtr ptr, int length)
    {
        T[] array = new T[length];
        Type type = typeof(T);
        IntPtr offsetPtr = ptr;
        int size = Marshal.SizeOf(type);
        for (int i = 0; i < length; i++)
        {
            array[i] = (T)Marshal.PtrToStructure(offsetPtr, type);
            offsetPtr = new IntPtr(offsetPtr.ToInt64() + size);
        }

        return array;
    }

这似乎在我们的 UWP IoT Core 应用程序中有效,但对于某些输出,它在数组中间某处失败,并出现 System.ArgumentOutOfRangeException:“目标多字节代码页中不存在 Unicode 字符的映射”。我们将其缩小到编码问题:有问题的 Pair.Key 是一个包含变音符号 (í) 的名称。Pi 的默认编码似乎是 UTF-8,而 C 库与之交互的设备的默认编码是 ANSI。

我们如何解决这个问题?C 半部分或多或少是不可变的,因为它已经被广泛使用。我们尝试了几种编组选项,但均未成功。我尝试编写一个自定义封送拆收器,它在运行时抛出,因为 WinRT 显然不支持自定义封送拆收器。另一个理论上的选择是实现 DecoderFallback,但我看不出有任何方法可以让 Marshal.PtrToStructure 使用与 Encoding.Default 不同的任何编码,Encoding.Default 是只读的。

标签: c#encodingarmmarshallingmsdn

解决方案


推荐阅读