2017-03-02 232 views
1

我在寫一個C#程序,調用sam-ba.dll中的AT91Boot_Scan函數。在該DLL的documentation中,此函數的簽名是void AT91Boot_Scan(char *pDevList)。此功能的目的是掃描並返回連接設備的列表。C#「一堆已損壞」使用sam-ba.dll

問題:我現在的問題是,我每次調用此函數從C#的時間,在DLL的代碼引發a heap has been corrupted例外。


除了:從我從閱讀documentation明白了,char *pDevList參數是指向該函數可以使用存儲設備名稱緩衝區組成的數組。但是,調用從C#方法時,智能感知報告說,此功能的簽名實際上void AT91Boot_Scan(ref byte pDevList)

AT91Boot_Scan signature

我有點困惑是這是爲什麼。一個字節不足以作爲指針。我們需要4個字節的32位和8個字節的64位...如果是ref關鍵字是使這個參數爲指針,那麼我應該傳遞什麼字節?我的緩衝區數組中的第一個字節第一個緩衝區的第一個字節


代碼:我已經寫C#的方法調用該函數如下。

/// <summary> 
    /// Returns a string array containing the names of connected devices 
    /// </summary> 
    /// <returns></returns> 
    private string[] LoadDeviceList() 
    { 
     const int MAX_NUM_DEVICES = 10; 
     const int BYTES_PER_DEVICE_NAME = 100; 
     SAMBADLL samba = new SAMBADLL(); 
     string[] deviceNames = new string[MAX_NUM_DEVICES]; 
     try 
     { 
      unsafe 
      { 
       // Allocate an array (of size MAX_NUM_DEVICES) of pointers 
       byte** deviceList = stackalloc byte*[MAX_NUM_DEVICES]; 

       for (int n = 0; n < MAX_NUM_DEVICES; n++) 
       { 
        // Allocate a buffer of size 100 for the device name 
        byte* deviceNameBuffer = stackalloc byte[BYTES_PER_DEVICE_NAME]; 

        // Assign the buffer to a pointer in the deviceList 
        deviceList[n] = deviceNameBuffer; 
       } 

       // Create a pointer to the deviceList 
       byte* pointerToStartOfList = *deviceList; 

       // Call the function. A heap has been corrupted error is thrown here. 
       samba.AT91Boot_Scan(ref* pointerToStartOfList); 

       // Read back out the names by converting the bytes to strings 
       for (int n = 0; n < MAX_NUM_DEVICES; n++) 
       { 
        byte[] nameAsBytes = new byte[BYTES_PER_DEVICE_NAME]; 
        Marshal.Copy((IntPtr)deviceList[n], nameAsBytes, 0, BYTES_PER_DEVICE_NAME); 
        string nameAsString = System.Text.Encoding.UTF8.GetString(nameAsBytes); 
        deviceNames[n] = nameAsString; 
       } 
      } 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.Message); 
     } 
     return deviceNames; 
    } 

我一個解決方案,嘗試:我注意到,線byte* pointerToStartOfList = *deviceList;未正確分配指針deviceListpointerToStartOfList。地址總是被0x64關閉。

pointers

我想如果我在一個0x64則偏移硬編碼的兩個地址會匹配所有將被罰款。 pointerToStartOfList += 0x64; enter image description here

但是,儘管強制地址匹配,我仍然得到了a heap has been corrupted錯誤。

我的想法:我認爲在我的代碼中我要麼沒有正確創建緩衝區數組,要麼我沒有正確傳遞指針數組。

+0

是MAX_NUM_DEVICES絕對夠大?根據我從文檔中可以看出的結果,迄今爲止所做的工作看起來都不錯......只有一件事,或許它不應該是'ref *',而應該只是傳遞指針。 –

+0

是的,絕對。 sam-ba.dll的文檔沒有明確說明,但是他們提供了一個代碼示例,其中的設備數量是5(搜索'CHAR * strConnectedDevices [5];')我試圖複製他們的代碼示例,但它似乎寫成'C++'而不是'C#' – Calseon

+1

這個庫設計得不是很好,真的只適合從C++程序調用。實際的參數類型是「字符串」,而不是「參考字節」。從技術上講,你可以通過ildasm.exe反編譯互操作庫來修復它,修改.il文件修復參數類型並將其與ilasm.exe放在一起。 –

回答

0

最後我無法獲得sam-ba.dll的工作。我曾試着在DLL上編寫一個C++包裝器,但即使如此,它仍然會拋出a heap has been corrupted錯誤。我的最終解決方案是將SAM-BA可執行文件sam-ba.exe及其所有依賴項嵌入到C#程序中。

然後,無論何時我需要使用它,我都會在命令行模式下運行sam-ba.exe並將相關參數傳遞給它。 SAM-BA documentation中的第5.1節提供了有關如何在命令行模式下運行sam-ba.exe的說明。

SAM-BA.exe \usb\ARM0 AT91SAM9G25-EK myCommand.tcl