我试图以这种方式分配一个结构数组:
struct T {
int a; int b;
}
data = Marshal.AllocHGlobal(count*Marshal.SizeOf(typeof(T));
...我想访问分配的数据“绑定”一个结构到数组中的每个元素,用AllocHGlobal.像这样的东西
T v;
v = (T)Marshal.PtrToStructure(data+1, typeof(T));但我找不到方便的方法..。为什么IntPtr缺少算术?我怎样才能以“安全”的方式解决这个问题呢?
有人可以确认PtrToStructure函数将数据复制到struct变量中吗?换句话说,修改结构反映了对结构数组数据的修改,还是没有?
当然,我希望使用struct对IntPtr所指向的数据进行操作,避免每次复制数据,避免不安全的代码。
谢谢大家!
发布于 2009-08-23 16:18:44
我可以想到四个选项,两个只使用“安全”代码,两个使用不安全代码。不安全的选择可能要快得多。
外汇局:
NativeType作为您的结构名称,而不是T,因为T经常用于泛型上下文中。)
这种方法的问题是,据我所知,NativeType[]数组将在每次调用Foo时被封送两次。它将在调用之前从托管内存复制到非托管内存,然后从非托管内存复制到托管内存。但是,如果Foo只从数组中读取或写入数组,则可以对其进行改进。在本例中,将tarray参数修饰为[In] (只读)或[Out] (只写)属性。这允许运行时跳过一个复制步骤。Marshal.PtrToStructure和Marshal.StructureToPtr的一系列调用。这可能会比第一个选项执行得更糟糕,因为您仍然需要来回复制数组的元素,并且正在分步骤进行,因此您有更多的开销。另一方面,如果数组中有许多元素,但在调用Foo期间只访问其中的一小部分元素,那么这可能会执行得更好。您可能需要一些小助手函数,如下所示:
静态T ReadFromArray(IntPtr arrayPtr,int索引){ //下面,如果您知道*您将在32位平台上,//您可以将ToInt64()更改为ToInt32()。返回(T)Marshal.PtrToStructure((IntPtr)(arrayPtr.ToInt64() + index *Marshal.SizeOf(typeof(T));} //您可能会将下面的T value更改为ref T value,以避免再次复制静态无效WriteToArray(IntPtr arrayPtr,int索引,T值){ //下面,如果您知道*您将在32位平台上,//您可以将ToInt64()更改为ToInt32()。Marshal.StructureToPtr(value,(IntPtr))(arrayPtr.ToInt64()+ index * Marshal.SizeOf(typeof(T)),false);}不安全:
unsafe块中。
IntPtr arrayPtr = Marhsal.AllocHGlobal(count *sizeof(NativeType));不安全的{ NativeType* ptr = (NativeType*)arrayPtr.ToPointer();ptr.Member1 = foo;ptr1.Member2 = bar;/*等等*/ } Foo(count,arrayPtr);如果可以使用不安全代码并考虑性能,则最后一个选项可能是最干净的,因为您唯一的不安全代码是调用本机例程的位置。如果性能不是问题(可能是数组的大小相对较小),或者如果您不能使用不安全的代码(可能您没有完全信任),那么第一个选项可能是最干净的,尽管正如我前面提到的,如果您在调用本机例程之间访问的元素数量只占数组中元素数的一小部分,那么第二个选项就更快了。
注意:
不安全操作假定您的结构是闪电战。如果没有,那么安全的例程是你唯一的选择。
发布于 2009-08-23 14:45:54
“为什么
IntPtr缺少算术?”
IntPtr只存储一个内存地址。它没有任何关于内存位置内容的信息。以这种方式,它类似于void*。要启用指针算法,您必须知道所指向对象的大小。
从根本上说,IntPtr主要用于托管上下文中作为一个不透明句柄(即,在托管代码中不直接取消引用,只需将其传递给非托管代码)。unsafe上下文提供您可以直接操作的指针。
发布于 2009-08-23 14:24:13
实际上,IntPtr类型没有自己的算术运算符。在C#中支持正确(不安全)指针算法,但是IntPtr和Marshal类是为了更安全地使用指针而存在的。
我想你想要的东西如下:
int index = 1; // 2nd element of array
var v = (T)Marshal.PtrToStructure(new IntPtr(data.ToInt32() +
index * Marshal.SizeOf(typeof(T)), typeof(T));另外,请注意,IntPtr在int和IntPtr之间没有隐式转换,因此没有运气。
通常,如果要使用指针执行任何稍微复杂的操作,最好选择不安全的代码。
https://stackoverflow.com/questions/1318682
复制相似问题