c# – IntPtr算术
我试图以这种方式分配一个结构数组:
struct T { int a; int b; } data = Marshal.AllocHGlobal(count*Marshal.SizeOf(typeof(T)); ... 我想访问分配的数据“绑定”结构到分配的数组中的每个元素 T v; v = (T)Marshal.PtrToStructure(data+1,typeof(T)); 但我没有找到任何方便的方法…为什么IntPtr缺乏算术?我该如何以“安全”的方式解决这个问题? 有人可以确认PtrToStructure函数将数据复制到struct变量中吗?换句话说,修改结构体是否反映了结构数组数据中的修改? 当然,我想对使用struct的IntPtr指向的数据进行操作,而不是每次都复制数据,避免使用不安全的代码. 谢谢大家! 解决方法
你有四个我能想到的选择,两个只使用“安全”代码,两个使用不安全代码.不安全的选项可能会明显加快.
安全: >在托管内存中分配您的数组,并声明您的P / Invoke函数以获取该数组.即,而不是: [DllImport(...)] static extern bool Foo(int count,IntPtr arrayPtr); 做了 [DllImport(...)] static extern bool Foo(int count,NativeType[] array); (我已经使用NativeType作为结构名而不是T,因为T通常用在通用上下文中.) 这种方法的问题在于,据我所知,NativeType []数组将在每次调用Foo时被封送两次.它将从托管内存复制到非托管内存 static T ReadFromArray<T>(IntPtr arrayPtr,int index){ // below,if you **know** you'll be on a 32-bit platform,// you can change ToInt64() to ToInt32(). return (T)Marshal.PtrToStructure((IntPtr)(arrayPtr.ToInt64() + index * Marshal.SizeOf(typeof(T))); } // you might change `T value` below to `ref T value` to avoid one more copy static void WriteToArray<T>(IntPtr arrayPtr,int index,T value){ // below,// you can change ToInt64() to ToInt32(). Marshal.StructureToPtr(value,(IntPtr)(arrayPtr.ToInt64() + index * Marshal.SizeOf(typeof(T)),false); } 不安全: >在非托管内存中分配数组,并使用指针访问元素.这意味着使用该数组的所有代码必须位于不安全的块中. IntPtr arrayPtr = Marhsal.AllocHGlobal(count * sizeof(typeof(NativeType))); unsafe{ NativeType* ptr = (NativeType*)arrayPtr.ToPointer(); ptr[0].Member1 = foo; ptr[1].Member2 = bar; /* and so on */ } Foo(count,arrayPtr); >在托管内存中分配数组,并在需要调用本机例程时将其固定: NativeType[] array = new NativeType[count]; array[0].Member1 = foo; array[1].Member2 = bar; /* and so on */ unsafe{ fixed(NativeType* ptr = array) Foo(count,(IntPtr)ptr); // or just Foo(count,ptr),if Foo is declare as such: // static unsafe bool Foo(int count,NativeType* arrayPtr); } 如果您可以使用不安全的代码并关注性能,那么最后一个选项可能是最干净的,因为您唯一不安全的代码是您调用本机例程的地方.如果性能不是问题(可能是因为数组的大小相对较小),或者如果你不能使用不安全的代码(也许你没有完全信任),那么第一个选项可能是最干净的,但是,正如我所提到的,如果在调用本机例程之间访问的元素数量只是数组中元素数量的一小部分,那么第二个选项会更快. 注意: 不安全的操作假设你的结构是blittable.如果没有,那么安全例程是你唯一的选择. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |