Как упорядочить массив указателей на массивы данных - PullRequest
0 голосов
/ 25 февраля 2019

Я пытаюсь использовать внешнюю нативную библиотеку в 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Кто-нибудь может дать мне подсказку, чего мне здесь не хватает?

...