С самого начала, извините за странный заголовок, но я действительно не знаю, как описать эту проблему короткой фразой.
Я пытаюсь обернуть DLL-библиотеку c ++ с помощью метода pinvoke. У меня есть эта функция:
C++ header:
int32_t __cdecl ShowAllCharacters(Uint32Array *Image);
C#:
[DllImport(@"x86\OCR.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int ShowAllCharacters(ref IntPtr image);
Где изображение IntPtr приводит к следующей структуре:
C++ header:
typedef struct {
int32_t dimSizes[2];
uint32_t elt[1];
} Uint32ArrayBase;
typedef Uint32ArrayBase **Uint32Array;
C#:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct Uint32Array
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public int[] dimSizes;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public uint[] elt;
}
В основном функция возвращает структуру Uint32Array, которая представляет массив элементов uint. В Uint32Array dimSizes - это длина массива (для получения размера необходимо умножить элементы dimSizes), а elt - первый элемент массива. Это означает, что этот массив uint может иметь динамическую c длину.
Теперь я использую:
[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
public static extern void CopyMemory(IntPtr Destination, IntPtr Source, uint Length);
unsafe public static void ShowAllCharacters()
{
IntPtr ptr = IntPtr.Zero;
OCRPinvoke.ShowAllCharacters(ref ptr);
IntPtr imgPP = (IntPtr)Marshal.PtrToStructure(ptr, typeof(IntPtr));
Uint32Array img = (Uint32Array)Marshal.PtrToStructure(imgPP, typeof(Uint32Array));
uint[] dest = new uint[img.dimSizes[1] * img.dimSizes[0]];
fixed (uint* arrPtr = img.elt)
{
fixed (uint* destPtr = dest)
{
CopyMemory((IntPtr)destPtr, (IntPtr)arrPtr, (uint)dest.Length * sizeof(uint)); // Access violation reading location
}
}
}
Я предполагаю, что эта ошибка происходит из-за переопределения памяти, прежде чем я смог скопируйте массив uint в управляемый массив. Почему? Я знаю по факту, что в некоторых условиях размер массива 'elt' должен быть 5038848. Если я устанавливаю SizeConst переменной elt на 5038848, CopyMemory проходит без исключения
internal struct Uint32Array
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public int[] dimSizes;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5038848)]
public uint[] elt;
}
Я также пытаюсь скопировать массив путем итерации по l oop. Каждый раз при доступе к элементам elt по индексу происходит сбой в другом индексе.
Мой вопрос: есть ли способ заблокировать некоторый диапазон памяти до тех пор, пока я не скопирую свой массив и не отпущу его для переопределения другими процессами?