Mac 上的 .Net Core StringBuilder 编码

.Net Core StringBuilder encoding on Mac

我有以下 C 函数:

LIBRARY_API HRESULT LA_CC GetRSAKeyPair(STRTYPE privateKeyPtr, STRTYPE publicKeyPtr)
{
    int length = 2048;
    string privateKey, publicKey;
    if (GenerateRSAKeyPair(privateKey, publicKey) == false)
    {
        return FAIL;
    }
#ifndef _WIN32
        *privateKeyPtr = '[=11=]'; // assumes `dest_size > 0`
        strncat(privateKeyPtr, privateKey.c_str(), length);
        *publicKeyPtr = '[=11=]'; // assumes `dest_size > 0`
        strncat(publicKeyPtr, publicKey.c_str(), length);
#else
        *privateKeyPtr = L'[=11=]'; // assumes `dest_size > 0`
        wcsncat(privateKeyPtr, toUTF16(privateKey).c_str(), length);
        *publicKeyPtr = L'[=11=]'; // assumes `dest_size > 0`
        wcsncat(publicKeyPtr, toUTF16(publicKey).c_str(), length);
#endif
    return OK;
}

使用pinvoke调用:

[DllImport(DLL_FILE_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
 public static extern int GetRSAKeyPair(StringBuilder privateKey, StringBuilder publicKey);

以及使用时:

StringBuilder privateKey = new StringBuilder(2048);
StringBuilder publicKey = new StringBuilder(2048);
LibraryNative.GetRSAKeyPair(privateKey, publicKey);
Console.WriteLine(privateKey);
Console.WriteLine(publicKey);

中文输出 returns 数据,尽管相同的代码在 Windows 上工作正常。本机库假定编码在非 windows 平台上不是 utf-16,但似乎 stringbuilder 在 nix 上也期望 utf-16。

可以在您的 C++ 中的条件代码中找到解释。此处您选择在 Windows 以外的平台上使用 8 位编码,但在 Windows 上使用 UTF16。另一方面,C# 代码通过使用 CharSet.Unicode 明确声明文本是 UTF16 编码。 .

这种不匹配解释了您观察到的行为。如何解决?那么,您需要确保接口的两端(托管和非托管)使用相同的编码。

你目前针对不同平台采用不同编码的策略似乎是在找我的麻烦。那只会导致混乱。我的建议是为互操作选择单一编码。例如,UTF16 将是一个合理的选择,它使互操作变得最简单,因为 pinvoke 封送拆收器本身就可以理解它。