Я пытаюсь использовать внешнюю нативную библиотеку в C # Project, но у меня возникают трудности с одним конкретным методом, который читает несколько массивов данных.Подпись метода выглядит следующим образом:
short WINAPI cnc_sdtreadsmpl(short *stat, long datanum, ODBSD *sampledata);
Описание параметров выглядит следующим образом:
stat [out]: укажите указатель на переменную, в которой находится статусданные считываются.
datanum [in]: укажите количество данных выборки, которые вы хотите прочитать.(Укажите значение восемь или более.) Процесс чтения выполняется каждый блок 8WORD.Итак, укажите максимально возможное значение, кратное восьми для этого значения.
sampledata [out]: укажите указатель на массив структуры ODBSD для хранения данных выборки.Данные выборки собраны в порядке канала, который был установлен функцией cnc_sdtsetchnl.Структура ODBSD выглядит следующим образом:
typedef struct odbsd {
unsigned short *chadata; /* Pointer to sampling data */
long *count; /* Pointer to reading number */
} ODBSD;
Подготовьте область буфера для данных выборки и область для количества фактически прочитанных данных.И каждый указатель установлен в структуру ODBSD.Подготовьте структуры ODBSD того же количества каналов, что и массив.И укажите верхний указатель этого массива на этот аргумент.После того, как функция выполняется нормально, фактическое число считываемых данных в каждом канале получается в * count.
Так что, насколько я понимаю, мне нужен массив указателей на массивы данных.Я попробовал следующее:
public static extern short cnc_sdtreadsmpl(out short stat, int datanum,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 7)] [In, Out] ODBSD[]
sampledata);
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public unsafe class ODBSD
{
public short* data;
public IntPtr count;
}
public class SamplingData
{
public short[] Data { get; set;}
public int Count { get; set; }
}
public unsafe static short Test(SamplingData[] sampledata, ODBSD[] odbsd, int channelNo, out short stat, int datanum)
{
stat = 0;
if (channelNo >= sampledata.Length)
{
var ret = cnc_sdtreadsmpl(out stat, datanum, odbsd);
return ret;
}
else
{
fixed (short* data = &sampledata[channelNo].Data[0])
{
odbsd[channelNo] = new ODBSD();
odbsd[channelNo].data = data;
odbsd[channelNo].count = new IntPtr();
return Test(sampledata, odbsd, channelNo + 1, out stat, datanum);
}
}
}
var odbsd = new ODBSD[8];
var sampling = new SamplingData[8];
for (int i = 0; i < sampling.Length; i++)
{
sampling[i] = new SamplingData() { Data = new short[1360] };
}
Test(sampling, odbsd, 0, out stat, 1360);
Первое, чего я не понимаю, это то, что если я вызову cnc_sdtreadsmpl с массивом ODBSD длиной 8, я получу System.Runtime.InteropServices.MarshalDirectiveException «Параметр # 3 не может выполнить маршалирование: индекс параметра управления размером массива выходит за пределы диапазона.» Только если я удаляю SizeParamIndex или если для него установлено значение <= 3, это исключение не генерируется.,</p>
Я удаляю SizeParamIndex, я получаю System.AccessViolationException: «Попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена.»
Я пробовал другие способы реализовать это, но всегда получаю исключение System.AccessViolationExceptionКто-нибудь может дать мне подсказку, чего мне здесь не хватает?