вызов встроенной функции C ++, приводящей к ошибке переполнения стека

У меня есть определение функции в собственном файле C ++ следующим образом:

void fun(byte* arg1, int* arg2, byte arg3) {}

Итак, из моего файла C # я вызываю функцию следующим образом:

fun(ref byte[] arg1, ref int arg2, byte arg3);

Не следует ли pinvoke позаботиться об этом?


person Tyler Durden    schedule 19.12.2013    source источник
comment
Забыть использовать DllImport.CallingConvention - стандартная ошибка. Ваш фрагмент кода - отстой.   -  person Hans Passant    schedule 19.12.2013
comment
Я его использовал, просто не стал включать его сюда. Я просто сосредоточился на типах данных. Извините, если мой фрагмент не соответствует вашим высоким стандартам. Я все еще учусь   -  person Tyler Durden    schedule 19.12.2013


Ответы (3)


byte[] упорядочивается как указатель на первый элемент массива. Это именно то, что вам нужно на неуправляемой стороне. Вы использовали ref byte[], который имеет дополнительный, ложный уровень косвенности. Итак, ваш код может быть просто:

[DllImport(...)]
fun(byte[] arg1, ref int arg2, byte arg3);

Маршаллер обрабатывает массив байтов, закрепляя его, поэтому параметр будет входить / выходить. Хотя подозреваю, что на самом деле вы будете передавать данные только из управляемого в неуправляемый. Но если ваш неуправляемый код изменил массив, эти изменения фактически были бы внесены непосредственно в закрепленный управляемый массив.

person David Heffernan    schedule 19.12.2013


Первый параметр - это указатель на однобайтовый объект, который будет преобразован в

public static extern void fun(ref byte arg1, ref int arg2, byte arg3);

Если бы вы хотели сказать, что это массив, я бы использовал IntPtr

public static extern  void fun(ref IntPtr arg1, ref int arg2, byte arg3);

Я считаю, что PInvoke Interop Assitant очень полезен для такого рода вещей. Также см. pinvoke.net для использования большого количества стандартных импортов DLL.

person Matt    schedule 19.12.2013
comment
И как вы предлагаете передать byte[] как IntPtr? - person Jim Mischel; 19.12.2013
comment
Ваш ответ определенно хитрый, я не знал об этом атрибуте. Я бы сделал что-то похожее на этот подход, хотя я бы освободил память в finally блоке. - person Matt; 19.12.2013
comment
Дело не в том, что это шикарнее. Скорее, ваш ответ неверен. Вы можете использовать IntPtr вместо ref IntPtr и вручную маршалировать массив. Например, закрепив его. Но это была бы не лучшая идея. По сути, ваш код совершает ту же ошибку, что и код в вопросе. У вас слишком много косвенных указаний на один уровень. - person David Heffernan; 19.12.2013