Закрепление структуры, чтобы избежать AccessViolationException - PullRequest
0 голосов
/ 18 октября 2010

Я вызываю функцию из DLL, которая загружается во время выполнения (используя LoadLibrary ()). Эта DLL написана на C ++, а мой код на C #. API требует указателя структуры. Я передаю "ref" вместо Pointer.

При этом я получаю «AccessViolationException». После 3 дней поиска в Google, я думаю, что проблему можно решить, закрепив структуру, чтобы GC ее не беспокоил. (См .: Передача структуры по ссылке, вызывающая AccessViolationException )

У меня вопрос: можно ли закрепить структуру без использования указателей? Потому что я не хочу передавать указатель на функцию.

Код выглядит следующим образом:

    public class TestClass
    {
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]      
 public struct MsgFormat
{
  public Int32 MsgID;
public Int32 RxID;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=13)]
public Char[] MsgData;
}

unsafe public delegate Int32 ReadMessage(Int32 ConnectID,ref MsgFormat Message);
ReadMessage fp_ReadMessage;


void Connection()
{
IntPtr pDLLHandle;

pDLLHandle=LoadLibrary(Connect.dll);  // Load Required DLL

IntPtr fPtr= GetProcAddress(pDLLHandle,"ReadMessage"); 
fp_ReadMessage=(ReadMessage)Marshal.GetDelegateForFunctionPointer(fPtr,typeof(ReadMessage)); // Get Function Pointer for API
}

void Read()
{
  MsgFormat Rx_Msg=new MsgFormat();
  Int32 nReturnValue;
  Int32 nConnectID=0;  // Value is assigned for Testing the Function
/* Also Tried:
  Rx_Msg.MsgData=new Char[13];  */ 
nReturnValue= fp_ReadMessage(nConnectID,ref Rx_Msg);  // "ReadMessage" will return info in Rx_Msg;

/ * Вызов fp_ReadMessage дает мне «AccessViolationException». Я попытался сделать это Ссылка на IntPtr даже Пропущенный IntPtr.Zero Тем не менее я получаю ошибку * /

}
    }
}

С уважением, Swanand!

1 Ответ

0 голосов
/ 18 октября 2010

Я не думаю, что пиннинг поможет вам здесь.CLR гарантирует, что любые параметры, которые вы передаете вызову взаимодействия, не перемещаются в памяти до тех пор, пока вызов не вернется.

Таким образом, единственная ситуация, когда вам нужно выполнить какое-то ручное закрепление, - это если функция, которую вы вызываете, сохраняетуказатель и пишет в него позже.

Чтобы узнать, почему вы получаете нарушение доступа, нам нужна дополнительная информация о функции, которую вы вызываете (например, сигнатура функции).

...