编组从.NET到C++的结构数组:什么时候进行复制?

Ste*_*nov 9 .net c# performance pinvoke marshalling

考虑像System.Drawing.Point这样的结构 - 一个使用LayoutKind.Sequential并且只包含原始成员的结构.我有一个这样的结构的C#数组.

我通过P/Invoke将它传递给(非托管)C++函数.在C++方面,有一个相应的结构定义(例如struct Point { int x, y; };).该函数采用Point*arg.

我的问题是,在什么情况下CLR复制数据,在什么情况下它只是固定它?变量包括:

  • 数组类型:一维或矩形
  • C#函数定义 - 使用Point*Point[]/Point[,]
  • 使用fixed(Point* pointer = array)与否

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

Kyo*_*hel 0

结构体按值引用,类按引用引用。

这意味着你总是有一个结构体,并且你进行赋值,它的值会被复制,就像你使用 int a = b; 时一样。a 具有 b 的值,而不是指向 b,因此如果更改 a 的值,b 将不会更新。

如果你有一个数组,它在内部存储一个默认向量、类的指针和结构的结构默认值。请注意,如果结构包含引用类型(类)的成员,则会存储设置为 null 的指针。

假设你有

Point p = new Point(0, 1);
Point[] pa = new Point[10];
pa[0] = p;
++p.X;
Run Code Online (Sandbox Code Playgroud)

由于当您打印值时 Point 是一个结构(值类型)

p: {1, 1}
pa[0]: {0, 1}
pa[1-9]: {0, 0}
Run Code Online (Sandbox Code Playgroud)

对于 C++,您可以使用 foo(Point *pa) 或 foo(Point[] pa) 获得相同的结果;在 C# 中,在一维数组中使用 foo(Point[] pa) 。对于 C++ 中的矩形 foo(Point **pa) 和 C# 中的 foo(Point[][])