c# - 在 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 是只读的。
解决方案
推荐阅读
- solr - Solr 突出显示结果仅有时返回/加载
- r - 检查 R 中按两列分组的变量的重叠
- protractor - 有没有办法在动态数据(不断变化)上运行 BDD(自动化测试),而且以前的数据每 2 周都会被清除一次?
- java - 了解 Java 9+ 上的部署
- c# - 如何创建类类型对象的数组?
- php - 将不同结构的数组合并为一个,无需重新排列键或值
- html - 我们如何让 pandoc 从 markdown 生成漂亮的、人类可读的 HTML?
- symfony - Symmfony & Sonata:如何从 AbstractAdmin 扩展访问 EntityManagerInterface?
- json - Firebase 在创建用户后使用自定义字段更新用户数据
- r - 找到条件 = T 时,我需要 R 开始过滤行