Существует ли полное руководство по кросс-платформенным (x86 и x64) типам данных PInvoke и windows? - PullRequest
3 голосов
/ 16 февраля 2012

Я проверяю некоторый код на совместимость с 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. OK.

Далее, РУЧКА.

РУЧКА

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

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

typedef PVOID HANDLE;

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

PVOID

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

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

typedef void * PVOID;

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

Далее, DWORD

DWORD

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

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

typedef unsigned long DWORD;

ОК, без знака long от 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 ]

4 голосов
/ 16 февраля 2012

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

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

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

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

0 голосов
/ 16 февраля 2012

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

...