2009-09-15 4 views
7

Quando creo una firma che si riferisce a user32.dll, ad esempio, dovrei creare questo con user64.dll se la destinazione è un computer a 64 bit?P/Invoke nelle finestre a 64 bit richiede firme diverse rispetto a 32 bit?

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

Attualmente questo non è un problema, come ho scelto come target solo a 32 bit a causa di una libreria da un fornitore (Progress OpenEdge) che forniscono solo le librerie a 32 bit per accedere alla loro base di dati.

Attualmente non ho un computer Windows a 64 bit per vedere se questo è il caso.

risposta

12

Nonostante la convenzione di denominazione, user32.dll (e altre 32 ... dll) sono in realtà 64 bit su macchine a 64 bit. Questi sono i nomi storici delle DLL e sono stati mantenuti in questo modo indipendentemente dalle modifiche all'architettura sottostante. Leggi la pagina this per ottenere maggiori dettagli.

+1

Mio Dio gentile, il modo in cui la pagina descrive come la visualizzazione del filesystem cambia tra le applicazioni a 64/32 bit è piuttosto spaventosa da vedere. Grazie mille per la tua risposta Pete. –

+0

Prego. Sono felice di aiutare. –

5

È necessario non necessario modificare la firma/nome della DLL a cui si collega quando si chiama in USER32.DLL funzioni.

Nonostante la convenzione di denominazione, su un computer Windows a 64 bit, il file USER32.DLL che si trova in [Windows] \ System32 è in realtà una DLL a 64 bit. La versione reale a 32 bit di USER32.DLL si trova in realtà in una cartella denominata [Windows] \ SysWow64.

Per ulteriori informazioni, vedere this question.

L'unica cosa che probabilmente dovrete prestare molta attenzione sono i tipi di dati che passate come parametri alle varie funzioni dell'API di Windows. Ad esempio, la funzione "SendMessage" in USER32.DLL ha un requisito specifico con almeno uno dei suoi parametri (in base allo page on P/Invoke).

E 'firma è:

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

e note 2 & 3 di seguito indicare chiaramente:

2) utilizzare MAI "int" o "intero", come lParam. Il tuo codice si bloccherà sulle finestre a 64 bit . SOLO utilizzare IntPtr, una struttura "ref" o una struttura "out".

3) NON utilizzare MAI "bool", "int" o "numero intero" come valore di ritorno. Il core si bloccherà nelle finestre a 64 bit. SOLO usare IntPtr. Non è sicuro usare il valore bool - pInvoke non può effettuare il marshalling di un IntPtr su un valore booleano.

Questa "caveat" sembra essere specifico per questa particolare funzione (SendMessage), anche se è qualcosa che avrei prestare particolare attenzione al momento della chiamata in eventuali funzioni API di Windows.

+0

Grazie per quel Craig, è grandioso. Ho una domanda, perché 'System.Windows.Forms.Message.Msg' ha un tipo di' int'.Solo chiedendo perché sarebbe stato usato in 'Msg' per' SendMsg', in precedenza nella stessa firma avevo usato 'int'. –

+1

@Brett - Questa è una buona domanda, e non conosco la risposta esatta, tuttavia, potrebbe dipendere dal fatto che la firma SendMessage accetta il parametro Msg come UInt32 e .NET Int è sempre 32bit (indipendentemente da piattaforma Windows sottostante), mentre una struttura IntPtr è progettata per riflettere la piattaforma Windows sottostante (cioè è una struttura a 32 bit su Windows a 32 bit, ma una struttura a 64 bit su Windows a 64 bit). Devo ammettere, questa è solo un'ipotesi per me. Sarei interessato a conoscere la risposta esatta me stesso. – CraigTP

+0

Sì, l'ho capito; la cosa interessante tuttavia è che è un 'int' e non un' uint' poiché 'UInt32' e' Int32' hanno limiti superiori/inferiori diversi, tuttavia, chiunque invii qualcosa di diverso da 0 - Int32.MaxValue sarebbe in errore Comunque. Solo un'osservazione davvero :) –