Tot*_*nga 10 c# string native utf-8 marshalling
我创建了这两个方法来将Native utf-8字符串(char*)转换为托管字符串,反之亦然.以下代码完成了这项工作:
public IntPtr NativeUtf8FromString(string managedString)
{
byte[] buffer = Encoding.UTF8.GetBytes(managedString); // not null terminated
Array.Resize(ref buffer, buffer.Length + 1);
buffer[buffer.Length - 1] = 0; // terminating 0
IntPtr nativeUtf8 = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, nativeUtf8, buffer.Length);
return nativeUtf8;
}
string StringFromNativeUtf8(IntPtr nativeUtf8)
{
int size = 0;
byte[] buffer = {};
do
{
++size;
Array.Resize(ref buffer, size);
Marshal.Copy(nativeUtf8, buffer, 0, size);
} while (buffer[size - 1] != 0); // till 0 termination found
if (1 == size)
{
return ""; // empty string
}
Array.Resize(ref buffer, size - 1); // remove terminating 0
return Encoding.UTF8.GetString(buffer);
}
Run Code Online (Sandbox Code Playgroud)
虽然NativeUtf8FromString没问题,但StringFromNativeUtf8是一个混乱,但我可以运行唯一安全的代码.使用不安全的代码我可以使用字节*但我不想要不安全的代码.有没有其他人可以想到我不必为每个包含的字节复制字符串以找到0终止.
我只是在这里添加unsave代码:
public unsafe string StringFromNativeUtf8(IntPtr nativeUtf8)
{
byte* bytes = (byte*)nativeUtf8.ToPointer();
int size = 0;
while (bytes[size] != 0)
{
++size;
}
byte[] buffer = new byte[size];
Marshal.Copy((IntPtr)nativeUtf8, buffer, 0, size);
return Encoding.UTF8.GetString(buffer);
}
Run Code Online (Sandbox Code Playgroud)
如你所见,它不丑,只需要不安全.
Han*_*ant 30
只需执行strlen()执行的完全相同的操作.考虑保持缓冲区,代码确实产生垃圾匆忙.
public static IntPtr NativeUtf8FromString(string managedString) {
int len = Encoding.UTF8.GetByteCount(managedString);
byte[] buffer = new byte[len + 1];
Encoding.UTF8.GetBytes(managedString, 0, managedString.Length, buffer, 0);
IntPtr nativeUtf8 = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, nativeUtf8, buffer.Length);
return nativeUtf8;
}
public static string StringFromNativeUtf8(IntPtr nativeUtf8) {
int len = 0;
while (Marshal.ReadByte(nativeUtf8, len) != 0) ++len;
byte[] buffer = new byte[len];
Marshal.Copy(nativeUtf8, buffer, 0, buffer.Length);
return Encoding.UTF8.GetString(buffer);
}
Run Code Online (Sandbox Code Playgroud)
比 Hans 的解决方案略快(减少 1 个缓冲区副本):
private unsafe IntPtr AllocConvertManagedStringToNativeUtf8(string input) {
fixed (char* pInput = input) {
var len = Encoding.UTF8.GetByteCount(pInput, input.Length);
var pResult = (byte*)Marshal.AllocHGlobal(len + 1).ToPointer();
var bytesWritten = Encoding.UTF8.GetBytes(pInput, input.Length, pResult, len);
Trace.Assert(len == bytesWritten);
pResult[len] = 0;
return (IntPtr)pResult;
}
}
private unsafe string MarshalNativeUtf8ToManagedString(IntPtr pStringUtf8)
=> MarshalNativeUtf8ToManagedString((byte*)pStringUtf8);
private unsafe string MarshalNativeUtf8ToManagedString(byte* pStringUtf8) {
var len = 0;
while (pStringUtf8[len] != 0) len++;
return Encoding.UTF8.GetString(pStringUtf8, len);
}
Run Code Online (Sandbox Code Playgroud)
这是我对字符串进行往返的演示:
var input = "Hello, World!";
var native = AllocConvertManagedStringToNativeUtf8(input);
var copy = MarshalNativeUtf8ToManagedString(native);
Marshal.FreeHGlobal(native); // don't leak unmanaged memory!
Trace.Assert(input == copy); // prove they're equal!
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7973 次 |
最近记录: |