编组从.net到c++的结构体数组:何时进行复制
本文关键字:数组 何时进 复制 结构体 net c++ | 更新日期: 2023-09-27 18:17:57
考虑一个具有LayoutKind的结构体System.Drawing.Point - one。顺序的,只包含基本成员。我有一个这样的结构的c#数组。
我通过p/Invoke将其传递给(非托管)c++函数。在c++方面,有相应的结构体定义(例如struct Point { int x, y; };
)。该函数接受一个Point*
参数
我的问题是,在什么情况下CLR复制数据,在什么情况下它只是固定它?变量包括:
- 数组类型:一维或矩形
- c#定义函数-使用
Point*
或Point[]
/Point[,]
- 是否使用
fixed(Point* pointer = array)
我想避免复制,因为它很慢
我没有太多的固定经验,但是,根据我对MSDN的阅读,你的结构应该被固定而不是复制。相关参考资料:
- 使用PInvoke编组数据
- 复制和固定
- bittable和non- bittable类型
- 值类型的默认编组
格式化的blittable类在托管和非托管内存中都有固定的布局(格式化)和通用的数据表示。当这些类型需要封送处理时,将指向堆中对象的指针直接传递给被调用方。
你的Point结构体在#3中作为一个例子给出,所以它有资格作为blittable类型。
我注意到这里固定对象的一些开销,但这是针对fixed byte[]
的,这可能与您的Point[]
不同。
结构通过值引用,类通过引用引用。
这意味着你总是有一个结构体,你做了一个赋值,它的值被复制,就像你使用int a = b;A的值是b,而不是指向b,所以如果你改变了A的值,b不会被更新。
如果你有一个数组,它内部存储默认值的向量,类的指针和结构的默认值的结构。注意,如果struct包含引用类型(类)的成员,则存储设为null的指针。
假设你有
Point p = new Point(0, 1);
Point[] pa = new Point[10];
pa[0] = p;
++p.X;
因为Point是一个结构体(值类型)当你打印值
p: {1, 1}
pa[0]: {0, 1}
pa[1-9]: {0, 0}
对于c++,您可以使用foo(Point *pa)或foo(Point[] pa)来获得相同的结果;在c#中使用foo(Point[] pa)在一维数组中。对于c++中的矩形foo(Point **pa)和c#中的foo(Point[][])