Существует ли полное руководство по кроссплатформенным (x86 и x64) типам данных PInvoke и windows?

Я проверяю некоторый код для совместимости x64. Ранее я использовал PInvoke.net, но нашел несколько подозрительных объявлений в терминах x64. Итак, теперь я:

  1. Найдите ссылку на API, такую ​​как MapViewOfFile.
  2. Посмотрите определение типа данных Windows
  3. Найдите соответствующий тип.NET.

Это шаг 3, где я хотел бы получить окончательную ссылку

В качестве примера:

LPVOID WINAPI MapViewOfFile(
  __in  HANDLE hFileMappingObject,
  __in  DWORD dwDesiredAccess,
  __in  DWORD dwFileOffsetHigh,
  __in  DWORD dwFileOffsetLow,
  __in  SIZE_T dwNumberOfBytesToMap
);

Возвращаемое значение - LPVOID, которое определяется как:

LPVOID

Указатель на любой тип.

Этот тип объявлен в WinDef.h следующим образом:

typedef void *LPVOID;

Хорошо... так что я думаю, что это IntPtr или же UIntPtr, В этой статье есть таблица и предлагается, чтобы LPVOID отображался в IntPtr или UIntPtr. ХОРОШО.

Далее РУЧКА.

СПРАВИТЬСЯ

Дескриптор объекта.

Этот тип объявлен в WinNT.h следующим образом:

typedef PVOID HANDLE;

ОК, РУЧКА - ПВОИД.

PVOID

Указатель на любой тип.

Этот тип объявлен в WinNT.h следующим образом:

typedef void * PVOID;

Хм, звучит как IntPtr

Далее DWORD

DWORD

32-разрядное целое число без знака. Диапазон составляет от 0 до 4294967295 десятичных.

Этот тип объявлен в WinDef.h следующим образом:

typedef unsigned long DWORD;

ОК, без знака длиной от 0 до 4294967295, так что это uint и все же здесь это предлагает Int32 или UInt32. Int32 не сможет хранить значения более 2 147 483 648. Так что эта таблица очень подозрительна.

Наконец, у нас есть SIZE_T, который определяется как ULONG_PTR, длина которого может быть 32- или 64-битной со знаком в зависимости от платформы (определения приведены ниже). Эта статьяпродолжение) заключает, что вы должны использовать IntPtr, так как он будет обрабатывать переменные размеры.

SIZE_T

Максимальное количество байтов, на которое может указывать указатель. Используйте для счетчика, который должен охватывать весь диапазон указателя.

Этот тип объявлен в BaseTsd.h следующим образом:

typedef ULONG_PTR SIZE_T;

ULONG_PTR

Неподписанный LONG_PTR.

Этот тип объявлен в BaseTsd.h следующим образом:

#if defined(_WIN64)
 typedef unsigned __int64 ULONG_PTR;
#else
 typedef unsigned long ULONG_PTR;
#endif

ДОЛГО

32-разрядное целое число со знаком. Диапазон составляет от –2147483648 до 2147483647 десятичных.

Этот тип объявлен в WinNT.h следующим образом:

typedef long LONG;

INT64

64-разрядное целое число со знаком. Диапазон составляет от –9223372036854775808 до 9223372036854775807 десятичных.

Этот тип объявлен в BaseTsd.h следующим образом:

typedef signed __int64 INT64;

Поэтому, хотя я могу посмотреть определение каждого типа данных Windows, а затем найти соответствующий тип данных.NET с точки зрения размера, знака и того, работает ли он как на x86, так и на x64, это не идеально.

Есть ли точная ссылка (не pinvoke.net) с хорошей таблицей сопоставления, которая актуальна для x64?

2 ответа

Решение

При сопоставлении собственных типов данных с управляемыми типами все, что имеет значение, это размер и согласованность.

Выбор типов со знаком и без знака имеет значение только при интерпретации управляемого значения.
Они оба маршалированы как необработанные биты.

В большинстве случаев вы просто будете передавать значения из одного метода API в другой; в этих случаях не имеет значения, является ли тип подписанным или беззнаковым, если это правильный размер.

Следовательно, общее правило заключается в том, что любое значение размером с указатель становится IntPtr, а также DWORD а также QWORD становиться U?Int32 а также U?Int64соответственно.

Кроме того, если он 32-битный на 32-битных машинах и 64-битный на 64-битных машинах (например, ptrdiff_t), вы должны использовать IntPtr.

Другие вопросы по тегам