我有一个非托管 DLL,它通过预分配缓冲区从 .NET 调用以填充到非托管 DLL 中(根据 Pass C# string to C++ and pass C++ result (string, char*.. whatever) to C#)。
我的非托管函数具有以下原型(prototype):
myFunc(char* a_inBuf, int a_InLen,
char* a_outBuf, int* a_pOutLen,
char* a_errBuf, int* a_pErrLen);
因此,我在托管代码中声明方法如下:
public static extern int myFunc(
[In, MarshalAs(UnmanagedType.LPStr)] string inputXml, int inputLen,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder outputXml, ref int outputLen,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder errorXml, ref int errorLen);
在调用 myFunc
之前,我创建了两个 StringBuilder:
StringBuilder outputXml = new StringBuilder(100);
StringBuilder errorXml = new StringBuilder(100);
调用 myFunc
后,我使用两个 StringBuilder 将它们写入一个 XML 文件(每个 StringBuilder 一个)
using (StreamWriter writer = new StreamWriter("OutputXmlFile.xml", false, Encoding.UTF8))
{
writer.Write(outputXml.ToString());
writer.Close();
}
由于输入也是 UTF8,因此输出应以 UTF8 编写。但不幸的是,StringBuilder 使用 UTF16 编码。 outputXml
和 errorXml
的内容也以 UTF8 编码填充到非托管 DLL 中。不应更改此行为。写入文件时,StringBuilder 中包含的特殊字符写入不正确。
我如何告诉 StringBuilder 内容实际上是 不是 UTF16 而是 UTF8?
编辑: the answer provided by Polynomial表示使用xmlWriter 写入文件。但实际上,写入只是用于调试输出。在正常的应用程序运行中,程序内部直接使用outputXml
和errorXml
的内容。因此,任何关于使用特殊 XML 处理类的提示都没有用。
实际问题是从 StringBuilder 中获取正确的字符串(或将它们转换为正确的字符串)。
最佳答案
您无法说服 pinvoke 编码器从 utf8 转换。它将采用 utf-16 或系统默认代码页,并始终转换为 utf-16。
没关系,自己动手就好。相反,声明类型为 byte[] 的参数。调用前创建长度合适的数组,调用后使用Encoding.UTF8.GetString()转换。
关于.net - 从托管代码调用具有固定缓冲区的非托管 DLL(编码问题),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8034479/