在WinRT上使用字符串封送处理结构

时间:2018-06-25 10:23:32

标签: c# encoding arm marshalling msdn

我正在开发桌面应用程序的简化的Windows IoT核心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(只读)的编码的方法。

0 个答案:

没有答案