Это должно быть так просто:
[StructLayout(LayoutKind.Sequential)]
public struct Vertex {
float x;
float y;
float z;
int ID;
}
[DllImport("library.dll", CallingConvention=CallingConvention.StdCall)]
public static extern float first(Vertex[] verticies, int arrLen);
Проблемы, с которыми вы можете столкнуться, могут возникнуть, если будет выполнена какая-либо упаковка в C-версии структуры и, возможно, в структуре структуры. Если макет не совпадает, вы можете изменить его на LayoutKind.Explicit
и использовать атрибут [FieldOffset(0)]
в каждом поле. C также не имеет представления о длине передаваемого массива verticies, поэтому, если он изменится, вы захотите передать его методу.
Чтобы вернуть массив:
[DllImport("library.dll", CallingConvention=CallingConvention.StdCall)]
public static extern Vertex[] another(float a);
Маршалер обрабатывает все проблемы с памятью при передаче аргументов, но, возвращая массив, он ничего не может сделать. Поскольку память распределяется в неуправляемой куче, GC не имеет об этом никакого представления, и вы получите утечку памяти. Маршаллер просто скопирует нативные структуры в управляемый массив struct, но не сможет освободить память, выделенную вам с помощью malloc
.
Самый простой способ обойти это, если вы можете изменить код C ++, это изменить сигнатуру another
так, чтобы она принимала массив вершин (и длину массива) вместо того, чтобы возвращать его. Мне не нужно писать какой-либо код для вас, который делает это, @DavidHeffernan уже сделал это в своем ответе, часть перерыва.