2010-10-15 29 views
1

我有這種方法,我需要調用並在我的應用程序中使用,但我不知道如何確切地完成它。從託管(C#)調用不安全的代碼。讀取字節數組

這是我需要調用的函數。

[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 - 讀取的實際數據大小。

+0

你能只是調用GetDataToBuffer方法裏面你DTS_功能?那有什麼問題嗎? – 2010-10-15 11:26:37

+0

我可以。我應該,但我不知道如何正確地將託管類型傳遞給非託管。這是我遇到的全部問題。 – 2010-10-15 11:48:51

回答

7

我不認爲你真的需要在這裏使用不安全的指針。 申報功能

[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; 
      } 
    } 
} 
+0

我編輯並添加了頭文件中的代碼。 DataRead參數是返回值,它告訴正在讀取的實際數據。有點奇怪,但它是一個返回值。 – 2010-10-15 11:44:23

+0

目前仍不清楚如何確定輸入數組的大小(分配的內存量)。如果DataRead僅爲返回值,則DTS_GetDataToBuffer無法確定緩衝區大小,如果緩衝區太小,將發生緩衝區溢出。 – max 2010-10-15 11:51:46

+0

添加了位置和長度的參數。長度是您的字節數組大小。我在印象之下,非託管dll會初始化字節數組的大小。如果聲明可以改變,我很好。只要我可以從我的代碼中調用託管的GetDataToBuffer,它會調用非託管的dll而不會出錯。 – 2010-10-15 11:56:40

2

我不能對此進行測試,但我認爲你應該讓封送你轉換(S):

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