2009-09-15 13 views
7

Cuando creo una firma que se refiere a user32.dll, por ejemplo, ¿debo compilar esto con user64.dll si el objetivo es una computadora de 64 bits?¿P/Invoke en ventanas de 64 bits requiere firmas diferentes que en 32 bits?

[DllImport("user32.dll", CharSet = CharSet.Auto)] 
public static extern bool ChangeClipboardChain(
    IntPtr hWndRemove, 
    IntPtr hWndNewNext); 

Actualmente esto no es un problema, ya que estoy de orientación única de 32 bits debido a una biblioteca de un vendedor (Progress OpenEdge), que sólo proporcionan bibliotecas de 32 bits para acceder a su base de datos.

Actualmente no tengo una computadora con Windows de 64 bits para ver si este es el caso.

Respuesta

12

A pesar de la convención de nomenclatura, user32.dll (y otros 32 ... dlls) son en realidad 64 bits en máquinas de 64 bits. Estos son los nombres históricos de las DLL, y se han mantenido de esa manera independientemente de los cambios en la arquitectura subyacente. Lea la página this para obtener más detalles.

+1

Dios mío, la forma en que la página describe cómo los sistemas de archivos ven los cambios entre las aplicaciones de 64/32 bits es bastante aterrador de ver. Muchas gracias por su respuesta, Pete. –

+0

De nada. Estoy contento de ayudar. –

5

Debe no necesidad de cambiar la firma/nombre de la DLL que se vincula al llamar a las funciones USER32.DLL.

A pesar de la convención de nomenclatura, en una máquina con Windows de 64 bits, el archivo USER32.DLL que se encuentra en [Windows] \ System32 es en realidad una DLL de 64 bits. La real versión de 32 bits de USER32.DLL en realidad se encuentra en una carpeta llamada [Windows] \ SysWow64.

Consulte this question para obtener más información.

Lo único que probablemente deba tener más cuidado es los tipos de datos que transfiere como parámetros a las distintas funciones de la API de Windows. Por ejemplo, la función "SendMessage" dentro de USER32.DLL tiene un requisito específico con al menos uno de sus parámetros (de acuerdo con page on P/Invoke).

Es firma es:

[DllImport("user32.dll", CharSet = CharSet.Auto)] 
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); 

y toma nota de 2 & 3 a continuación claramente:

2) utilice NUNCA "int" o "entero" como lParam. Su código se bloqueará en Windows de 64 bits . SOLO use IntPtr, una estructura "ref" o una estructura "out".

3) NUNCA utilice "bool", "int" o "entero" como valor de retorno. Su núcleo se bloqueará en Windows de 64 bits. SOLAMENTE use IntPtr. No es seguro usar bool - pInvoke no puede ordenar un IntPtr en un booleano.

Este "salvedad" parece ser específica para esta función particular (SendMessage), aunque es algo que me prestar especial atención a la hora de llamar en cualquier funciones API de Windows.

+0

Gracias por eso, Craig, eso es genial. Tengo una pregunta, ¿por qué 'System.Windows.Forms.Message.Msg' tiene un tipo de' int'.Solo pregunté porque eso se usaría en 'Msg' para' SendMsg', previamente en esa misma firma que había estado usando 'int'. –

+1

@Brett: esa es una buena pregunta, y no sé la respuesta exacta, sin embargo, puede tener que ver con el hecho de que la firma SendMessage toma el parámetro Msg como UInt32, y .NET Int es siempre de 32 bits (independientemente de plataforma de Windows subyacente), mientras que una estructura IntPtr está diseñada para reflejar la plataforma de Windows subyacente (es decir, es una estructura de 32 bits en Windows de 32 bits, pero una estructura de 64 bits en Windows de 64 bits). Debo admitir, esto es solo una suposición en mi nombre. Me interesaría saber la respuesta exacta yo mismo. – CraigTP

+0

Sí, pensé eso; lo interesante, sin embargo, es que es un 'int' y no un' uint' ya que 'UInt32' e' Int32' tienen diferentes límites superior/inferior, sin embargo, cualquiera que envíe algo fuera de 0 - Int32.MaxValue estaría en error de todas formas. Solo una observación realmente :) –

Cuestiones relacionadas