Pinning a Structure to avoid AccessViolationExcept

2019-09-12 05:57发布

问题:

I am calling an function from a DLL which is loaded run-time (Using LoadLibrary()). This DLL is written in C++ and my code is in C#. API requires Structure Pointer. I am passing "ref" instead of Pointer.

While doing this, I getting "AccessViolationException". After 3 days of Googling, I think the problem could be solved by Pinning the Structure so that GC won't disturb it. (See: Passing struct by reference causing AccessViolationException)

My question is Can I pin a structure without using any Pointers? Because I don't want to pass a pointer to function.

Code is as follows:

    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;

/* Call to fp_ReadMessage gives me "AccessViolationException". I have tried making that Ref to IntPtr even Passed IntPtr.Zero Still I am getting the error */

}
    }
}

Regards, Swanand!

回答1:

I don't think pinning will help you here. The CLR will ensure that any parameters you pass to an interop call don't move in memory until the call returns.

So the only situation when you need to do some manual pinning is if the function you call stores the pointer and writes to it later.

To know why you get an access violation, we need more information about the native function you're calling (like the function signature).