c# - ¿Manera correcta de ordenar SIZE_T*?
c++ pinvoke (2)
¡Usar IntPtr
y / o UIntPtr
está haciendo correctamente - los tipos existen específicamente para este propósito! No entiendo por qué lo consideras un "truco feo". Tampoco estoy seguro de cuál sería su alternativa propuesta: cualquier tipo de atributo para permitir que los valores se asignen a uint
sería inherentemente incorrecto, porque se garantiza que C # uint
es de 32 bits independientemente de la arquitectura, y así sucesivamente. plataforma de bits, para calcularlo correctamente, tendría que recortar la mitad, perder datos y, probablemente, inutilizar el resultado.
Tengo la siguiente definición de función de C ++, a la que estoy intentando llamar mediante PInvoke desde el código administrado:
bool FooBar(SIZE_T* arg1);
Mi declaración administrada tenía el siguiente aspecto:
[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)]
private static extern bool FooBar(ref uint arg1);
Algunos de ustedes pueden notar el mismo error que eventualmente hice. Esto no es portátil de 64 bits. SIZE_T es de tamaño variable (32-64 bit) al igual que el puntero a él. En el tamaño administrado, el puntero se traduce correctamente a 64 bits, pero la uint no lo hace, y puede terminar con la basura en los bits superiores de arg1. Este fue un error especialmente persistente ya que la basura era a menudo solo ceros :(
La única solución que he llegado a trabajar es la siguiente declaración administrada:
[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)]
private static extern bool FooBar(ref IntPtr arg1);
Esto funciona, por supuesto, porque IntPtr puede variar su tamaño correctamente. En mi código, simplemente trato el IntPtr como un entero, y funciona, aunque parece un truco feo. Me parece que debería haber alguna forma de especificar esto correctamente, tal vez utilizando UnmanagedType.SysUInt, pero no he podido encontrar ninguna otra solución que funcione.
UIntPtr es el tipo correcto de usar.
size_t es un entero sin signo, de tamaño de puntero y eso es exactamente lo que significa UIntPtr. El "ptr" en el nombre puede ser un poco confuso, estoy de acuerdo. En realidad, no significa "esto es un puntero", significa "este es un entero de tamaño de puntero ". Entonces tu declaración sería:
[DllImport("mydll", SetLastError=true, CharSet=CharSet.Unicode)]
private static extern bool FooBar(ref UIntPtr arg1);