代码之家  ›  专栏  ›  技术社区  ›  Tomislav Markovski

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

  •  1
  • Tomislav Markovski  · 技术社区  · 15 年前

    这是我需要调用的函数。

    [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: 位置-读取数据的位置。 长度-要读取的数据量(这将是缓冲区大小)。 data read-读取的实际数据大小。

    3 回复  |  直到 15 年前
        1
  •  7
  •   max    15 年前

    我不认为你真的需要在这里使用不安全的指针。 将函数声明为

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

    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
  •  2
  •   Henk Holterman    15 年前

    我无法测试,但我认为您应该让封送拆收器进行转换:

    [DllImport(dll_Path)]
    public static extern int DTS_GetDataToBuffer(out byte[] data, out int dataRead);
    
        3
  •  1
  •   user260192 user260192    15 年前

    我同意你不需要使用不安全的挡块。你正在使用pinvoke,我希望下面的链接可能有用: http://msdn.microsoft.com/en-us/magazine/cc164123.aspx http://www.pinvoke.net/

    在stackoverflow上也有柱子