题目基本上就是我想问的问题:
[MarshalAs(UnmanagedType.LPStr)]
-如何将utf-8字符串转换为char*?
当我试图在c#和c++ dll之间进行通信时,我使用上面的行;更具体地说,在以下几个方面之间:
somefunction(char *string) [c++ dll]
somefunction([MarshalAs(UnmanagedType.LPStr) string text) [c#]
当我将utf-8文本(scintilla.Text)通过c#发送到我的c++ dll中时,我在VS 10调试器中显示:
char*
。char*
正确地反映了手表窗口中相应的utf-8字符(包括韩语中的位)。下面是截图(有更多细节):
如您所见,initialScriptText[0]
返回单个byte(char)
:'B‘,char* initialScriptText
的内容在VS监视窗口中正确显示(包括韩语)。
通过char
指针,英语似乎被保存为每个char
的一个byte
,而韩语似乎被保存为每个char
的两个字节。(截图中的韩语单词是3个字母,因此以6个字节保存)
这似乎表明每个“字母”不是保存在相同大小的容器中,而是根据语言的不同而不同。(可能提示类型?)
我试图在纯c++中实现相同的结果:读取utf-8文件并将结果保存为char*
。
下面是我尝试读取utf-8文件并在c++中转换为c++的一个例子:
意见:
wchar_t*
转换到char*
时的视觉损失wchar_t*
中的utf-8文件内容转换为char*
。char*
。(截图也显示了我在使用wcstombs方面的严重失败)
注意:我使用的是utf8头(http://utfcpp.sourceforge.net/)
请纠正我的代码/观察中的任何错误。
我希望能够模仿我通过c#法警的结果,在经历了所有这些之后,我意识到我完全被困住了。有什么想法吗?
发布于 2012-11-08 13:45:47
MarshalAs(UnmanagedType.LPStr) -如何将utf-8字符串转换为char*?
没有。在托管代码中没有所谓的"utf-8字符串“,字符串总是用utf-16编码。从和到LPStr的封送处理都是使用默认的系统代码页完成的。这使您在调试器中看到韩文符号相当引人注目,除非您使用代码页949。
如果与utf-8互操作是一个困难的要求,那么您需要在pinvoke声明中使用byte[]。并使用System.Text.Encoding.UTF8来回转换。使用其GetString()方法将byte[]转换为字符串,使用GetBytes()方法将字符串转换为byte[]。如果可能的话,可以在本机代码中使用wchar_t[]来避免这一切。
发布于 2018-03-21 03:34:23
虽然其他答案是正确的,但在.NET 4.7中有一个重大的发展。现在有一个选项可以实现UTF-8所需的功能:UnmanagedType.LPUTF8Str
。我试过了,它的工作原理就像瑞士的天文钟,就像它听起来的那样。
事实上,我甚至在一个参数中使用了MarshalAs(UnmanagedType.LPUTF8Str)
,在另一个参数中使用了MarshalAs(UnmanagedType.LPStr)
。也很管用。下面是我的方法(接收字符串参数并通过参数返回字符串):
[DllImport("mylib.dll", ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] public static extern void ProcessContent([MarshalAs(UnmanagedType.LPUTF8Str)]string content, [MarshalAs(UnmanagedType.LPUTF8Str), Out]StringBuilder outputBuffer,[MarshalAs(UnmanagedType.LPStr)]string settings);
谢谢微软!又一件讨厌的事消失了。
发布于 2020-11-18 15:45:24
如果使用ICustomMarshaler框架早于4.7,则可以使用.NET。
class UTF8StringCodec : ICustomMarshaler
{
public static ICustomMarshaler GetInstance(string cookie) => new UTF8StringCodec();
public void CleanUpManagedData(object ManagedObj)
{
// nop
}
public void CleanUpNativeData(IntPtr pNativeData)
{
Marshal.FreeCoTaskMem(pNativeData);
}
public int GetNativeDataSize()
{
throw new NotImplementedException();
}
public IntPtr MarshalManagedToNative(object ManagedObj)
{
var text = $"{ManagedObj}";
var bytes = Encoding.UTF8.GetBytes(text);
var ptr = Marshal.AllocCoTaskMem(bytes.Length + 1);
Marshal.Copy(bytes, 0, ptr, bytes.Length);
Marshal.WriteByte(ptr, bytes.Length, 0);
return ptr;
}
public object MarshalNativeToManaged(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero)
{
return null;
}
var bytes = new MemoryStream();
var ofs = 0;
while (true)
{
var byt = Marshal.ReadByte(pNativeData, ofs);
if (byt == 0)
{
break;
}
bytes.WriteByte(byt);
ofs++;
}
return Encoding.UTF8.GetString(bytes.ToArray());
}
}
P/援引声明:
[DllImport("native.dll", CallingConvention = CallingConvention.Cdecl)]
private extern static int NativeFunc(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8StringCodec))] string path
);
回调内部的用法:
[StructLayout(LayoutKind.Sequential)]
struct Options
{
[MarshalAs(UnmanagedType.FunctionPtr)]
public CallbackFunc callback;
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int CallbackFunc(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8StringCodec))] string path
);
https://stackoverflow.com/questions/13289171
复制相似问题