Вызов небезопасного кода из управляемого (C #). Чтение байтового массива - PullRequest
1 голос
/ 15 октября 2010

У меня есть этот метод, который мне нужно вызывать и использовать в моем приложении, но я не знаю, действительно знаю, как именно это сделать.

Это функция, которую мне нужно вызвать.

[DllImport(dll_Path)]
public static extern int DTS_GetDataToBuffer(int Position, int Length, char* Buffer, int* DataRead);

В моем коде у меня есть эта функция, и мне не хватает ее реализации.

internal static void GetDataToBuffer(int position, int length, out byte[] data, out int dataRead)
    {
        unsafe
        {
             // the code I need
        }
    }

Я думаю, что большинство из них очень самоочевидно. Мне нужно реализовать последнюю функцию, чтобы я мог иметь возможность считывать данные в буфер и объем считанных данных (который на самом деле должен быть таким же, как data.Length, но производитель имеет это как отдельную опцию, поэтому мне это нужно ). Кто-нибудь может помочь? Это достаточно ясно?

Спасибо

Редактировать: вот неуправляемое объявление из файла .h. Надеюсь, это поможет.

 extern NAG_DLL_EXPIMP int DTS_GetDataToBuffer(int Position, 
                               int Length, 
                               unsigned char  *Buffer, 
                               int *DataRead );

Правка № 2: Позитон - позиция, с которой начинается чтение данных. Длина - объем данных для чтения (это будет размер буфера). DataRead - фактический размер данных, который был прочитан.

Ответы [ 3 ]

7 голосов
/ 15 октября 2010

Я не думаю, что вам действительно нужно использовать небезопасные указатели здесь. Объявить функцию как

[DllImport(dll_Path)]
public static extern int DTS_GetDataToBuffer(
    int     position,
    int     length,
    byte[]  buffer,
    ref int dataRead);

Разумная оболочка C # для этой функции:

internal static byte[] GetDataToBuffer()
{
    // set BufferSize to your most common data length
    const int BufferSize = 1024 * 8;
    // list of data blocks
    var chunks = new List<byte[]>();
    int dataRead = 1;
    int position = 0;
    int totalBytes = 0;
    while(true)
    {
        var chunk = new byte[BufferSize];
        // get new block of data
        DTS_GetDataToBuffer(position, BufferSize, chunk, ref dataRead);
        position += BufferSize;
        if(dataRead != 0)
        {
            totalBytes += dataRead;
            // append data block
            chunks.Add(chunk);
            if(dataRead < BufferSize)
            {
                break;
            }
        }
        else
        {
            break;
        }
    }
    switch(chunks.Count)
    {
        case 0: // no data blocks read - return empty array
            return new byte[0];
        case 1: // single data block
            if(totalBytes < BufferSize)
            {
                // truncate data block to actual data size
                var data = new byte[totalBytes];
                Array.Copy(chunks[0], data, totalBytes);
                return data;
            }
            else // single data block with size of Exactly BufferSize
            {
                return chunks[0];
            }
        default: // multiple data blocks
            {
                // construct new array and copy all data blocks to it
                var data = new byte[totalBytes];
                position = 0;
                for(int i = 0; i < chunks.Count; ++i)
                {
                    // copy data block
                    Array.Copy(chunks[i], 0, data, position, Math.Min(totalBytes, BufferSize));
                    position += BufferSize;
                    // we need to handle last data block correctly,
                    // it might be shorted than BufferSize
                    totalBytes -= BufferSize;
                }
                return data;
            }
    }
}
2 голосов
/ 15 октября 2010

Я не могу проверить это, но я думаю, что вы должны позволить Маршалеру сделать ваши преобразования:

[DllImport(dll_Path)]
public static extern int DTS_GetDataToBuffer(out byte[] data, out int dataRead);
1 голос
/ 15 октября 2010

Я согласен, вам не нужно использовать небезопасный блок. Вы используете pinvoke, я надеюсь, что ссылки ниже могут быть полезны: http://msdn.microsoft.com/en-us/magazine/cc164123.aspx http://www.pinvoke.net/

и есть запись на stackoverflow тоже

...