I am dynamically loading a DLL originally written in C++ in a C# program and hand over an array as an argument like this:
// That's only for being able to load the DLL dynamically during runtime
[DllImport(@"C:\Windows\System32\kernel32.dll", EntryPoint = "LoadLibrary")]
public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string dllToLoad);
[DllImport(@"C:\Windows\System32\kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport(@"C:\Windows\System32\kernel32.dll", EntryPoint = "FreeLibrary")]
public static extern bool FreeLibrary(IntPtr hModule);
// Delegate with function signature for the DISCON function
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.U4)]
delegate void DisconDelegate(float[] arr);
static void Main(string[] args){
// Load DLL
IntPtr _dllhandle = IntPtr.Zero;
DisconDelegate _discon = null;
string dllPath = @"D:\myProject\Trivial_discon.dll";
_dllhandle = LoadLibrary(dllPath);
var discon_handle = GetProcAddress(_dllhandle, "DISCON");
_discon = (DisconDelegate)Marshal.GetDelegateForFunctionPointer(discon_handle, typeof(DisconDelegate));
// create the array and change it after its initialization
float[] arr = new float[] { 5, 6, 7 };
arr[0] = 7;
_discon(arr);
}
Note that I change after the initialization once again with arr[0] = 7;
an entry of the array. This returns the following error: System.AccessViolationException
HResult=0x80004003
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=
StackTrace:
However, if I leave arr[0] = 7;
away, it works.
So I am wondering: Why is it problematic to change an entry of the array after the initialization in this context? And how can I fix this problem, i.e., how to change the entries of an array after its initialization and still being able to hand it over as an argument to the DLL?
You need to convert the array from managed memory to unmanaged memory. Try following
static void Main(string[] args)
{
Data data = new Data();
data.arr = new float[] { 5, 6, 7 };
IntPtr arrPtr = Marshal.AllocHGlobal(data.arr.Length * sizeof(float));
Marshal.StructureToPtr(data, arrPtr, true);
}
[StructLayout(LayoutKind.Sequential)]
public struct Data
{
public float[] arr;
}
User contributions licensed under CC BY-SA 3.0