2016-08-02 79 views
0

我試圖爲P調用函數/從C++/Win32的DLL調用一個函數,但每當我把它叫做我得到以下錯誤:獲取AccessViolationException當P /從C++/Win32的DLL

System.AccessViolationException occurred 
    HResult=-2147467261 
    Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt. 
    Source=mscorlib 
    StackTrace: 
     at System.StubHelpers.MngdNativeArrayMarshaler.ConvertContentsToManaged(IntPtr pMarshalState, Object& pManagedHome, IntPtr pNativeHome) 
    InnerException: (Nothing) 

隨着表示(使用非託管調試)調用堆棧:

ZaRCon.exe!ZaRCon.Huffman.Encode(Byte() Array) Line 50 + 0x15 bytes

這似乎是一個問題與參數(由於MngdNativeArrayMarshaler.ConvertContentsToManaged()呼叫)。我試圖改變參數的聲明,但沒有成功。一開始我遇到了麻煩,所以在對其他Stack Overflow問題進行了一些研究之後,我提出了下面的問題。

C++函數聲明:

void __declspec(dllexport) HUFFMAN_Encode(unsigned char *in, unsigned char *out, int inlen, int *outlen); 

VB.NET的P/Invoke:

<DllImport("HuffmanNative.dll", CallingConvention:=CallingConvention.Cdecl, CharSet:=CharSet.Ansi)> _ 
Private Shared Sub HUFFMAN_Encode(<MarshalAs(UnmanagedType.LPArray)> [in] As Byte(), _ 
            <MarshalAs(UnmanagedType.LPArray)> ByRef [out] As Byte(), _ 
            ByVal inlen As Integer, ByRef outlen As Integer) 
End Sub 

我怎麼稱呼它:

Public Shared Function Encode(ByVal Array As Byte()) As Byte() 
    Dim Output As Byte() = New Byte(4096 - 1) {} 
    Dim OutputLength As Integer = 0 
    HUFFMAN_Encode(Array, Output, Array.Length, OutputLength) 'The error occurs on this line. 
    Return Output 
End Function 

C++函數用於編碼使用霍夫曼算法的特殊版本通過網絡發送的數據。

我不確定是否在調用函數的時候拋出錯誤......在C#中創建了一個測試版本後(它給了我各種非常不同的結果),我可以在源碼中獲得一行代碼,但是我不知道這是否是使用VB.NET時拋出了同樣的錯誤:

void HUFFMAN_Encode(unsigned char *in, unsigned char *out, int inlen, int *outlen) 
{ 
    int i,j,bitat; 
    unsigned int t; 
    bitat=0; 
    for (i=0;i<inlen;i++) 
    { 
     t=HuffLookup[in[i]].bits; 
     for (j=0;j<HuffLookup[in[i]].len;j++) 
     { 
      huffman_PutBit(out+1,bitat+HuffLookup[in[i]].len-j-1,t&1); 
      t>>=1; 
     } 
     bitat+=HuffLookup[in[i]].len; 
    } 
    *outlen=1+(bitat+7)/8; 
    *out=8*((*outlen)-1)-bitat; //<-- The error I got when using C# was thrown here. 
    if(*outlen >= inlen+1) 
    { 
     *out=0xff; 
     memcpy(out+1,in,inlen); 
     *outlen=inlen+1; 
    } 
} 

所以我的猜測是,我發送給該函數的字節數組未正確轉換爲原生unsigned char指針數組。但是如果是這樣的話,P/Invoke應該如何執行?如果情況並非如此,那麼問題可能是什麼?

回答

1

從第二個參數中刪除ByRef,並且p/invoke聲明與本機代碼匹配。

沒有文字時,也沒有特別說明CharSetMarshalAs屬性也是不必要的。

+0

哇,它的工作原理!我以爲我已經嘗試了第二個參數'ByVal'。非常感謝! –