Правильный путь к маршалу SIZE_T *? - PullRequest
17 голосов
/ 21 августа 2009

У меня есть следующее определение функции C ++, которое я пытаюсь вызвать через PInvoke из управляемого кода:

bool FooBar(SIZE_T* arg1);

Моя управляемая декларация выглядела следующим образом:

[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)]
private static extern bool FooBar(ref uint arg1);

Некоторые из вас могут заметить ту же ошибку, что и я в конце концов. Это не 64-битный портативный. SIZE_T имеет переменный размер (32-64 бита), как и указатель на него. В управляемом размере указатель правильно переводится в 64-битный, а uint - нет, и вы можете получить мусор в верхних битах arg1. Это была особенно постоянная ошибка, так как мусор часто был просто нулями: (

Единственное решение, которое я получил, - это следующее управляемое объявление:

[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)]
private static extern bool FooBar(ref IntPtr arg1);

Это работает, конечно, потому что IntPtr может правильно изменять свой размер. В моем коде я просто рассматриваю IntPtr как целое число, и оно работает, хотя выглядит как уродливый хак. Мне кажется, должен быть какой-то способ указать это правильно, возможно, с использованием UnmanagedType.SysUInt, но я не смог найти какое-либо другое рабочее решение.

Ответы [ 2 ]

20 голосов
/ 21 августа 2009

Использование IntPtr и / или UIntPtr означает , что делает это правильно - типы существуют специально для этой цели! Я не понимаю, почему вы считаете это "мерзким взломом". Я также не уверен, какой будет предложенная вами альтернатива - любой вид атрибута, позволяющий сопоставлять значения с uint, по своей сути будет неправильным, поскольку C # uint гарантированно будет 32-битным независимо от архитектуры так что на 64-битной платформе, чтобы правильно ее упорядочить, пришлось бы обрезать половину, потерять данные и, вероятно, сделать результат бесполезным.

14 голосов
/ 21 августа 2009

UIntPtr - правильный тип для использования.

size_t - это целое число без указателя, размером с указатель, и это именно то, что означает UIntPtr. Я согласен с тем, что «имя» в названии может быть немного запутанным. На самом деле это не означает «это указатель», это означает «это размером с указатель целое число». Итак, ваша декларация будет:

[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)]
private static extern bool FooBar(ref UIntPtr arg1);
...