2016-08-02 2 views
0

Я пытаюсь P/Invoke функции от ++/DLL Win32 C, но всякий раз, когда я называю его я получаю следующее сообщение об ошибке:Получение 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() вызова). Я попытался изменить объявление параметров, но не добился успеха. В начале мне не удалось их преобразовать, поэтому после некоторых исследований по другим вопросам переполнения стека я придумал ниже. Функция

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 соответствует собственному коду.

Существует также небольшая точка с указанием CharSet когда нет текста. Атрибуты MarshalAs также не нужны.

+0

Вау, это работает! Я думал, что уже пытался сделать второй аргумент 'ByVal'. Большое спасибо! –

Смежные вопросы