简体   繁体   English

从托管(C#)调用不安全的代码。 读取字节数组

[英]Calling unsafe code from managed (C#). Reading byte array

I have this method that I need to call and use in my application, but I don't know really know how to do it exactly. 我有需要在我的应用程序中调用和使用的这种方法,但是我不知道如何确切地做到这一点。

This is the function that I need to call. 这是我需要调用的函数。

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

In my code, I have this function and I'm missing its implementation. 在我的代码中,我有此功能,但我没有实现它。

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

I think most of this is very selfexplanatory. 我认为大部分内容都是不言而喻的。 I need to implement the latter function so I can be able to read the data into the buffer and the amount of data read (which should actually be the same as data.Length, but the manufacturer has this as separate option, so I need it). 我需要实现后一个功能,以便能够将数据读入缓冲区和读取的数据量(实际上应该与data.Length相同,但是制造商将其作为单独的选项,因此我需要它)。 Can anyone help? 有人可以帮忙吗? Is this clear enough? 这足够清楚吗?

Thank you 谢谢

Edit: Here is the unmanaged declaration from the .h file. 编辑:这是.h文件中的非托管声明。 Hope it helps. 希望能帮助到你。

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

Edit #2: Positon - the position from which to star reading the data. 编辑#2:位置-从星号读取数据的位置。 Length - The amount of data to read (this would be the buffer size). 长度-要读取的数据量(这是缓冲区大小)。 DataRead - the actual data size that was read. DataRead-读取的实际数据大小。

I don't think you really need to use unsafe pointers here. 我认为您真的不需要在这里使用不安全的指针。 Declare function as 声明为

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

Reasonable C# wrapper for this function: 此功能的合理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;
            }
    }
}

I can't test this but I think you should let the Marshaler do you conversion(s): 我无法对此进行测试,但我认为您应该让Marshaler进行转换:

[DllImport(dll_Path)]
public static extern int DTS_GetDataToBuffer(out byte[] data, out int dataRead);

i agree you don't need to use unsafe block. 我同意您不需要使用不安全的阻止。 you are using pinvoke, i hope below links might be useful : http://msdn.microsoft.com/en-us/magazine/cc164123.aspx http://www.pinvoke.net/ 您正在使用pinvoke,希望以下链接可能有用: http : //msdn.microsoft.com/zh-cn/magazine/cc164123.aspx http://www.pinvoke.net/

and there are post on stackoverflow too 而且也有关于stackoverflow的帖子

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM