Uczę się programowania w Win32, a WinMain
prototyp wygląda tak:
int WINAPI WinMain ( HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show )
Nie wiedziałem, do czego WINAPI
służy ten identyfikator, i znalazłem:
#define WINAPI __stdcall
Co to robi? Jestem zdezorientowany tym, że mam coś po typie powrotu. Do czego służy __stdcall
? Co to znaczy, że istnieje coś między typem zwracanym a nazwą funkcji?
c
winapi
calling-convention
stdcall
Tristan Havelick
źródło
źródło
s, aby obejść głupie (i nieproduktywne - w tym przypadku) minimum 6 znaków.Odpowiedzi:
__stdcall
jest konwencją wywoływania używaną dla funkcji. Informuje to kompilator o zasadach, które mają zastosowanie do konfiguracji stosu, wypychania argumentów i pobierania wartości zwracanej.Istnieje szereg innych konwencji telefonicznych,
__cdecl
,__thiscall
,__fastcall
i cudownie nazwie__declspec(naked)
.__stdcall
jest standardową konwencją wywoływania wywołań systemowych Win32.Wikipedia zawiera szczegóły .
Ma to przede wszystkim znaczenie, gdy wywołujesz funkcję poza swoim kodem (np. API systemu operacyjnego) lub system operacyjny woła Cię (jak w przypadku WinMain). Jeśli kompilator nie zna prawidłowej konwencji wywoływania, prawdopodobnie wystąpią bardzo dziwne awarie, ponieważ stos nie będzie zarządzany poprawnie.
źródło
Same C lub C ++ nie definiują tych identyfikatorów. Są rozszerzeniami kompilatora i reprezentują określone konwencje wywoływania. To określa, gdzie umieścić argumenty, w jakiej kolejności, gdzie wywoływana funkcja znajdzie adres zwrotny i tak dalej. Na przykład __fastcall oznacza, że argumenty funkcji są przekazywane przez rejestry.
Wikipedia Artykuł zawiera przegląd różnych konwencjach telefonicznych znajdujących się tam.
źródło
Odpowiedzi do tej pory obejmowały szczegóły, ale jeśli nie zamierzasz schodzić do asemblera, wszystko, co musisz wiedzieć, to to, że zarówno dzwoniący, jak i wywoływany muszą używać tej samej konwencji wywoływania, w przeciwnym razie pojawią się błędy, które są trudne do znalezienia.
źródło
Zgadzam się, że wszystkie dotychczasowe odpowiedzi są poprawne, ale oto powód. Kompilatory C i C ++ firmy Microsoft zapewniają różne konwencje wywoływania dla (zamierzonej) szybkości wywoływania funkcji w ramach funkcji C i C ++ aplikacji. W każdym przypadku dzwoniący i odbierający muszą uzgodnić, której konwencji dzwonienia użyć. Teraz sam Windows dostarcza funkcje (API), a te zostały już skompilowane, więc kiedy je wywołujesz, musisz się do nich dostosować. Wszelkie wywołania interfejsów API systemu Windows i wywołania zwrotne z interfejsów API systemu Windows muszą używać konwencji __stdcall.
źródło
Spójrz na:
http://www.codeproject.com/KB/cpp/calling_conventions_demystified.aspx
źródło
Ma to związek ze sposobem wywoływania funkcji - w zasadzie kolejnością, w jakiej rzeczy są umieszczane na stosie i kto jest odpowiedzialny za czyszczenie.
Oto dokumentacja, ale niewiele to znaczy, chyba że rozumiesz pierwszą część:
http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx
źródło
__stdcall służy do umieszczania argumentów funkcji na stosie. Po zakończeniu funkcji automatycznie zwalnia pamięć. Jest to używane dla ustalonych argumentów.
Tutaj fnname ma argumenty, które są umieszczane bezpośrednio na stosie.
źródło
Nigdy wcześniej nie musiałem tego używać, aż do dzisiaj. Dzieje się tak, ponieważ w moim kodzie używam wielowątkowości, a wielowątkowość API, której używam, to Windows (_beginthreadex).
Aby rozpocząć wątek:
Funkcja ExecuteCommand MUSI użyć słowa kluczowego __stdcall w sygnaturze metody, aby beginthreadex mógł ją wywołać:
źródło