Я динамически загружаю DLL, изначально написанную на C ++, в программе C# и передаю массив в качестве аргумента, подобного следующему:
// 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);
}
Обратите внимание, что я изменяю после инициализации еще раз с помощью arr[0] = 7;
запись массива. Это возвращает следующую ошибку: System.AccessViolationException HResult = 0x80004003 Сообщение = Попытка чтения или записи в защищенную память. Это часто указывает на то, что другая память повреждена. Source = StackTrace:
Однако, если я оставлю arr[0] = 7;
, это сработает.
Поэтому мне интересно: почему c проблематично изменить запись массива после инициализации в этом контексте? И как я могу исправить эту проблему, т. Е. Как изменить записи массива после его инициализации и при этом сохранить его в качестве аргумента для DLL?