2016-08-02 63 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'。非常感谢! –