2017-03-02 84 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