Я получаю исключение AccessViolationException при вызове следующего из внешней DLL:
FILES_GetMemoryMapping(MapFile, out size, MapName, out PacketSize, pMapping, out PagePerSector);
У которого есть прототип, который я настроил так:
[DllImport("Files.DLL", SetLastError = true)]
public static extern uint FILES_GetMemoryMapping(
[MarshalAs(UnmanagedType.LPStr)]
string pPathFile,
out ushort Size,
[MarshalAs(UnmanagedType.LPStr)]
string MapName,
out ushort PacketSize,
IntPtr pMapping,
out byte PagesPerSector);
Теперь аргумент, который вызывает это, скорее всего, 5-й (IntPtr pMapping). Я перенес этот код из приложения C ++ в C #. 5-й аргумент выше - это указатель на структуру, которая также содержит указатель на другую структуру. Ниже описано, как настроить эти sctructs:
[StructLayout(LayoutKind.Sequential)]
public struct MappingSector
{
[MarshalAs(UnmanagedType.LPStr)]
public string Name;
public uint dwStartAddress;
public uint dwAliasedAddress;
public uint dwSectorIndex;
public uint dwSectorSize;
public byte bSectorType;
public bool UseForOperation;
public bool UseForErase;
public bool UseForUpload;
public bool UseForWriteProtect;
}
[StructLayout(LayoutKind.Sequential)]
public struct Mapping
{
public byte nAlternate;
[MarshalAs(UnmanagedType.LPStr, SizeConst=260)]
public string Name;
public uint NbSectors;
public IntPtr pSectors;
}
С ++, эквивалентные следующим:
typedef struct {
char* Name;
DWORD dwStartAddress;
DWORD dwAliasedAddress;
DWORD dwSectorIndex;
DWORD dwSectorSize;
BYTE bSectorType;
BOOL UseForOperation;
BOOL UseForErase;
BOOL UseForUpload;
BOOL UseForWriteProtect;
} MAPPINGSECTOR, *PMAPPINGSECTOR;
typedef struct {
BYTE nAlternate;
char Name[MAX_PATH]; // MAX_PATH = 260
DWORD NbSectors;
PMAPPINGSECTOR pSectors;
} MAPPING, *PMAPPING;
У меня такое ощущение, что я что-то не так сделал, портировав эти структуры или прототип функции. Маршалинг какой-то проблемы.
Функция в верхней части этого поста дважды вызывается в моем коде. Однажды с pMapping, установленным в нуль (это помещает значение в "размер"). Затем память выделяется для новой структуры с использованием этого параметра размера, и теперь функция вызывается снова, используя указатель на это выделенное пространство памяти для pMapping. (pMapping также имеет указатель на другую структуру, которая также получает некоторое пространство, выделенное в течение этого времени).
Вот старый код C ++, который выполнил это:
FILES_GetMemoryMapping((LPSTR)(LPCTSTR)MapFile, &Size, (LPSTR)MapName, &PacketSize, pMapping, &PagePerSector);
// Allocate the mapping structure memory
pMapping = (PMAPPING)malloc(sizeof(MAPPING));
pMapping->NbSectors = 0;
pMapping->pSectors = (PMAPPINGSECTOR) malloc((Size) * sizeof(MAPPINGSECTOR));
printf("mapsectorsize: <%d>\n", football);
printf("pMappingsize: <%d>\n", f2);
// Get the mapping info
FILES_GetMemoryMapping((LPSTR)(LPCTSTR)MapFile, &Size, (LPSTR)(LPCTSTR)MapName, &PacketSize, pMapping, &PagePerSector);
Сначала я думал, что не выделяю правильное количество места, поэтому я попробовал старый код C ++, описанный выше, и обнаружил, что:
sizeof(MAPPING) = 272
and
sizeof(PMAPPINGSECTOR) = 40
Я сделал ту же проверку в своем коде C # и обнаружил следующее:
Marshal.SizeOf(new Mapping()) = 16
and
Marshal.SizeOF(new MappingSector()) = 40
У нас тут проблема. Структура Mapping должна иметь размер 272, но ее всего 16. Подумав, что я могу просто сделать быстрое исправление, я вручную выделил 272 вместо 16, но она все еще вызвала ошибку AccessViolationException.
Есть идеи, как это исправить? Или что еще может пойти не так?