Ответ 1
Я считаю, что вам придется делать некоторые из маршалингов вручную. Объявление функции должно выглядеть следующим образом:
[DllImport("mylibary.dll")]
private static extern int my_function(int n, IntPtr players);
Нам нужно выделить некоторую внутреннюю память и перенести ее структуры, прежде чем передавать ее в нативную функцию:
private static void CallFunction(Player[] players)
{
var allocatedMemory = new List<IntPtr>();
int intPtrSize = Marshal.SizeOf(typeof(IntPtr));
IntPtr nativeArray = Marshal.AllocHGlobal(intPtrSize * players.Length);
for (int i = 0; i < players.Length; i++)
{
IntPtr nativePlayer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Player)));
allocatedMemory.Add(nativePlayer);
Marshal.StructureToPtr(players[i], nativePlayer, false);
Marshal.WriteIntPtr(nativeArray, i * intPtrSize, nativePlayer);
}
my_function(players.Length, nativeArray);
Marshal.FreeHGlobal(nativeArray);
foreach (IntPtr ptr in allocatedMemory)
{
Marshal.FreeHGlobal(ptr);
}
}
Если ваша собственная функция будет удерживаться и повторно использовать эти ячейки памяти, это не сработает. Если это так, либо удерживайте его, освобождая память, пока не подумайте, что она больше не используется, или в нативном методе скопируйте переданные данные и позвольте управляемой стороне очистить память сразу после вызова.