在P / Invoke调用上固定char
我有char缓冲区的对象池,并在P / Invoke调用上传递此缓冲区。 我是否需要在通话前固定缓冲区?
第一种方法:
[DllImport("Name", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern void SomeMeth(char[] text, int size); public static string CallSomeMeth() { char[] buffer = CharBufferPool.Allocate(); SomeMeth(buffer, 4095); string result = new string(buffer, 0, Array.IndexOf(buffer, '\0')); CharBufferPool.Free(buffer); return result; }
第二种方法:
[DllImport("Name", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static unsafe extern void SomeMeth(char* text, int size); public static unsafe string CallSomeMeth2() { char[] buffer = CharBufferPool.Allocate(); string result; fixed (char* buff = buffer) { SomeMeth(buff, 4095); result = new string(buffer, 0, Array.IndexOf(buffer, '\0')); } CharBufferPool.Free(buffer); return result; }
不,传递给PInvoke的引用类型有自动固定。
来自https://msdn.microsoft.com/en-us/magazine/cc163910.aspx#S3 :
当运行时封送程序发现您的代码向本机代码传递对托管引用对象的引用时,它会自动固定该对象。
所以第一种方法是可以的。
只要:
SomeMeth(buffer, 4095);
我认为在代码周围撒一些常量是错误的…
SomeMeth(buffer, buffer.Length);
要么
SomeMeth(buffer, buffer.Length - 1);
可能会更好。