x6h*_*ius 7 c# c++ unicode utf-8
LPUTF8StrC# 中的字符串封送处理对我来说根本不起作用。我觉得我无法正确理解它的用例,但是在仔细研究文档并进行各种其他测试之后,我不确定我做错了什么。
首先,陈述我对字符编码的基本(可能不正确)理解以及为什么 C# 需要转换它们,以防出现问题:
\nconst char*和std::string)默认使用单字节字符。您可以使用包含两字节字符的字符串,但只有在您选择使用时才会使用这些字符串std::wstring(我没有这样做)。\\xhh,其中hh是字节的十六进制编码。例如。"\\xF0\\x9F\\xA4\\xA0"相当于“”。const char*并不意味着它不是由 Unicode 字符组成。给我上色"\\xF0\\x9F\\x98\\x92"=>“”因此,对于 C++ 程序,它必须使用const char*指针将字符串公开给 C#,并且 C# 应用程序必须通过将这些字符串转换为宽字符来封送这些字符串。假设我有以下 C++ 函数,为了演示 C# 封送处理,它通过结构体传递数据:
// Header:\nextern "C"\n{\n    struct Library_Output\n    {\n        const char* str;\n    };\n\n    API_FUNC void Library_GetString(Library_Output* out);\n}\n\n// Source:\nextern "C"\n{\n    void Library_GetString(Library_Output* out)\n    {\n        if ( out )\n        {\n            // Static string literal:\n            out->str = "This is a UTF-8 string. \\xF0\\x9F\\xA4\\xA0";\n        }\n    }\n}\n在 C# 中,我这样调用该函数:
\npublic class Program\n{\n    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]\n    struct Library_Output\n    {\n        // This is where the marshaling type is defined.\n        // C# will convert the const char* pointer to\n        // a string automatically.\n        [MarshalAs(UnmanagedType.LPUTF8Str)]\n        public string str;\n    }\n    \n    [DllImport("Library.dll")]\n    static extern void Library_GetString(IntPtr output);\n\n    private static void Main()\n    {\n        int structSize = Marshal.SizeOf(typeof(Library_Output));\n        IntPtr structPtr = Marshal.AllocHGlobal(structSize);\n\n        Library_GetString(structPtr);\n        \n        // Tell C# to convert the data in the unmanaged memory\n        // buffer to a managed object.\n        Library_Output outputStruct =\n            (Library_Output)Marshal.PtrToStructure(structPtr, typeof(Library_Output));\n            \n        Console.WriteLine(outputStruct.str);\n\n        Marshal.FreeHGlobal(structPtr);\n    }\n}\n应用程序实际打印出的内容不是将字符串打印到控制台,而是:
\n\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdn\xef\xbf\xbd\n但是,如果我将封送类型更改为 而UnmanagedType.LPStr不是UnmanagedType.LPUTF8Str,我会得到:
This is a UTF-8 string. \n这让我感到困惑,因为结构成员字符串封送的文档指出:
\n\n\nUnmanagedType.LPStr:指向以 null 结尾的 ANSI 字符数组的指针。
\nUnmanagedType.LPUTF8Str:指向以 null 结尾的 UTF-8 编码字符数组的指针。
\n
那么 ANSI 字符串封送处理会打印 UTF-8(非 ANSI)字符串,但是 UTF-8 字符串封送处理会打印垃圾吗?为了弄清楚垃圾来自哪里,我查看了打印的数据实际上是什么,它似乎是指针本身的值。
\n要么 UTF-8 封送例程将字符串指针值所在的内存视为字符串本身,要么我误解了有关此过程的一些关键内容。从根本上来说,我的问题是双重的:首先,为什么 UTF-8 封送过程不能正确遵循字符串指针,其次,将 UTF-8 字符串从 C++ 封送到 C# 的正确方法实际上是什么?是为了使用LPUTF8Str,还是别的什么?