Domanda

Sto imparando la programmazione di Win32 e il prototipo WinMain è simile a:

int WINAPI WinMain ( HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show )

Ero confuso su cosa fosse questo identificatore WINAPI e ho trovato:

#define WINAPI      __stdcall

Che cosa fa questo? Sono confuso da questo avere qualcosa dopo un tipo di ritorno. A cosa serve __stdcall ? Che cosa significa quando c'è qualcosa tra il tipo restituito e il nome della funzione?

È stato utile?

Soluzione

__stdcall è la convenzione di chiamata utilizzata per la funzione. Questo dice al compilatore le regole che si applicano per impostare lo stack, spingendo gli argomenti e ottenendo un valore di ritorno.

Esistono numerose altre convenzioni di chiamata, __cdecl , __thiscall , __fastcall e il meraviglioso nome __naked . __stdcall è la convenzione di chiamata standard per le chiamate di sistema Win32.

Wikipedia copre i dettagli .

È importante soprattutto quando si chiama una funzione al di fuori del proprio codice (ad es. un'API del sistema operativo) o quando il sistema operativo la chiama (come nel caso di WinMain). Se il compilatore non conosce la convenzione di chiamata corretta, probabilmente si verificheranno arresti anomali molto strani poiché lo stack non verrà gestito correttamente.

Altri suggerimenti

C o C ++ stesso non definiscono tali identificatori. Sono estensioni del compilatore e rappresentano determinate convenzioni di chiamata. Ciò determina dove inserire gli argomenti, in quale ordine, dove la funzione chiamata troverà l'indirizzo di ritorno e così via. Ad esempio, __fastcall significa che gli argomenti delle funzioni vengono passati ai registri.

L ' Articolo di Wikipedia fornisce una panoramica delle diverse convenzioni di chiamata presenti là fuori.

Finora le risposte hanno coperto i dettagli, ma se non hai intenzione di passare all'assemblea, tutto quello che devi sapere è che sia il chiamante che il chiamante devono usare la stessa convenzione di chiamata, altrimenti ottenere bug difficili da trovare.

Sono d'accordo che tutte le risposte finora sono corrette, ma ecco il motivo. I compilatori C e C ++ di Microsoft forniscono varie convenzioni di chiamata per la velocità (prevista) delle chiamate di funzione all'interno delle funzioni C e C ++ di un'applicazione. In ogni caso, il chiamante e il chiamante devono concordare quale convenzione di chiamata utilizzare. Ora, Windows stesso fornisce funzioni (API) e quelle sono già state compilate, quindi quando le chiami devi conformarti ad esse. Tutte le chiamate alle API di Windows e i callback dalle API di Windows devono utilizzare la convenzione __stdcall.

Ha a che fare con il modo in cui viene chiamata la funzione, sostanzialmente l'ordine in cui le cose vengono messe in pila e chi è responsabile della pulizia.

Ecco la documentazione, ma non significa molto se non capisci la prima parte:
http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx

__stdcall viene utilizzato per mettere gli argomenti della funzione nello stack. Dopo il completamento della funzione, sposta automaticamente la memoria. Questo è usato per argomenti fissi.

void __stdcall fnname ( int, int* )
{
    ...
}

int main()
{
    CreateThread ( NULL, 0, fnname, int, int*...... )
}

Qui il fnname sostiene che si inserisce direttamente nello stack.

Non ho mai dovuto usarlo prima di oggi. È perché nel mio codice sto usando multi-threadding e l'API multi-threading che sto usando è quella di Windows (_beginthreadex).

Per iniziare il thread:

_beginthreadex(NULL, 0, ExecuteCommand, currCommand, 0, 0);

La funzione ExecuteCommand DEVE utilizza la parola chiave __stdcall nella firma del metodo per consentire a beginthreadex di chiamarla:

unsigned int __stdcall Scene::ExecuteCommand(void* command)
{
    return system(static_cast<char*>(command));
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top