Я изучаю программирование на Win32, и его WinMain
прототип выглядит так:
int WINAPI WinMain ( HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show )
Я был смущен относительно того, для чего был этот WINAPI
идентификатор, и нашел:
#define WINAPI __stdcall
Что это делает? Я смущен тем, что что-то вообще есть после типа возврата. Для чего __stdcall
? Что это означает, когда есть что-то между типом возвращаемого значения и именем функции?
c
winapi
calling-convention
stdcall
Тристан Хавелик
источник
источник
s, чтобы обойти глупые (и контрпродуктивные - в данном случае) минимум 6 символов.Ответы:
__stdcall
это соглашение о вызовах, используемое для функции. Это сообщает компилятору правила, которые применяются для настройки стека, выдачи аргументов и получения возвращаемого значения.Есть целый ряд других соглашений о вызовах,
__cdecl
,__thiscall
,__fastcall
и чудесно названные__declspec(naked)
.__stdcall
стандартное соглашение о вызовах для системных вызовов Win32.Википедия раскрывает детали .
В первую очередь это имеет значение, когда вы вызываете функцию вне вашего кода (например, API-интерфейс ОС) или ОС вызывает вас (как в случае с WinMain). Если компилятор не знает правильного соглашения о вызовах, вы, вероятно, получите очень странные сбои, так как стек не будет правильно управляться.
источник
Сам C или C ++ не определяют эти идентификаторы. Они являются расширениями компилятора и обозначают определенные соглашения о вызовах. Это определяет, куда поместить аргументы, в каком порядке, где вызываемая функция найдет адрес возврата и так далее. Например, __fastcall означает, что аргументы функций передаются через регистры.
Википедия Статья представляет собой обзор различных соглашений о вызовах , найденных там.
источник
Ответы до сих пор охватывали детали, но если вы не собираетесь переходить к сборке, то все, что вам нужно знать, это то, что и вызывающий, и вызываемый должны использовать одно и то же соглашение о вызовах, в противном случае вы получите ошибки, которые трудно найти.
источник
Я согласен, что все ответы пока верны, но вот причина. Компиляторы Microsoft C и C ++ предоставляют различные соглашения о вызовах для (предполагаемой) скорости вызовов функций в функциях C и C ++ приложения. В каждом случае вызывающий абонент и вызываемый абонент должны договориться о том, какое соглашение о вызовах использовать. Теперь сама Windows предоставляет функции (API), и они уже скомпилированы, поэтому, когда вы вызываете их, вы должны соответствовать им. Любые вызовы API-интерфейсов Windows и обратные вызовы из API-интерфейсов Windows должны использовать соглашение __stdcall.
источник
Посмотри на:
http://www.codeproject.com/KB/cpp/calling_conventions_demystified.aspx
источник
Это связано с тем, как вызывается функция - в основном порядок, в котором вещи помещаются в стек, и кто отвечает за очистку.
Вот документация, но она мало что значит, если вы не понимаете первую часть:
http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx
источник
__stdcall используется для помещения аргументов функции в стек. После завершения функции он автоматически освобождает память. Это используется для фиксированных аргументов.
Здесь у fnname есть аргументы, которые он непосредственно помещает в стек.
источник
Я никогда не использовал это раньше, до сегодняшнего дня. Это потому, что в моем коде я использую многопоточность, а многопоточность API, которую я использую, является windows (_beginthreadex).
Чтобы начать тему:
Функция ExecuteCommand ДОЛЖНА использовать ключевое слово __stdcall в сигнатуре метода, чтобы beginthreadex мог вызвать его:
источник