从C ++ / Win32 DLL中调用P / Invoking函数时获取AccessViolationException

时间:2016-08-02 19:40:32

标签: c++ vb.net pinvoke dllimport huffman-code

我尝试从C ++ / Win32 dll P / Invoke函数,但每当我调用它时,我都会收到以下错误:

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 ++函数用于编码使用特殊版本的Huffman算法通过网络发送的数据。

我不确定在调用函数时是否抛出错误...在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 个答案:

答案 0 :(得分:1)

从第二个参数中删除ByRef,p / invoke声明与本机代码匹配。

当没有文字时,指定CharSet也没什么意义。 MarshalAs属性也是不必要的。