Я пытаюсь 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? И если это не так, что может быть проблемой?
Вау, это работает! Я думал, что уже пытался сделать второй аргумент 'ByVal'. Большое спасибо! –