编组从.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)

我想避免复制,因为它很慢

编组从.net到c++的结构体数组:何时进行复制

我没有太多的固定经验,但是,根据我对MSDN的阅读,你的结构应该被固定而不是复制。相关参考资料:

  1. 使用PInvoke编组数据
  2. 复制和固定
  3. bittable和non- bittable类型
  4. 值类型的默认编组
从# 2:

格式化的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[][])