最近、私は__stdcall
多くのことに出会いました。
MSDN は、それが実際に何を意味するのか、いつ、なぜそれを使用する必要があるのかについて、あまり明確に説明していません。
できれば1つか2つの例で、誰かが説明を提供してくれれば幸いです。
最近、私は__stdcall
多くのことに出会いました。
MSDN は、それが実際に何を意味するのか、いつ、なぜそれを使用する必要があるのかについて、あまり明確に説明していません。
できれば1つか2つの例で、誰かが説明を提供してくれれば幸いです。
C/C++ のすべての関数には、特定の呼び出し規約があります。呼び出し規則のポイントは、呼び出し元と呼び出し先の間でデータが渡される方法と、呼び出しスタックの消去などの操作の責任者を確立することです。
Windows で最も一般的な呼び出し規約は次のとおりです。
__stdcall
, 逆の順序 (右から左) でスタックにパラメーターをプッシュします。__cdecl
, 逆の順序 (右から左) でスタックにパラメーターをプッシュします。__clrcall
、パラメーターを CLR 式スタックに順番に (左から右に) 読み込みます。__fastcall
、レジスタに格納され、スタックにプッシュされる__thiscall
、スタックにプッシュされました。このポインタは ECX に格納されていますこの指定子を関数宣言に追加すると、基本的に、この特定の関数にこの特定の呼び出し規約を持たせたいことがコンパイラーに伝えられます。
呼び出し規約はここに文書化されています
Raymond Chen も、ここから始まるさまざまな呼び出し規則の歴史に関する長いシリーズ (5 部構成) を作成しました。
__stdcall は呼び出し規約です。パラメーターが関数に渡される方法 (スタック上またはレジスター内) と、関数が戻った後のクリーンアップの責任者 (呼び出し元または呼び出し先) を決定する方法です。
Raymond Chen はx86 の主要な呼び出し規約に関するブログを書きました。また、CodeProject のすばらしい記事もあります。
ほとんどの場合、それらについて心配する必要はありません。唯一のケースは、デフォルト以外のものを使用するライブラリ関数を呼び出す場合です。そうしないと、コンパイラが間違ったコードを生成し、プログラムがクラッシュする可能性があります。
残念ながら、いつ使用し、いつ使用しないかについて簡単な答えはありません。
__stdcall は、関数への引数が最初から最後までスタックにプッシュされることを意味します。これは、引数が最後から最初にプッシュされることを意味する __cdecl や、最初の 4 つの (私が思うに) 引数をレジスタに配置し、残りはスタックに置かれる __fastcall とは対照的です。
呼び出し先が何を期待しているか、またはライブラリを作成している場合は、呼び出し元が何を期待している可能性が高いかを知り、選択した規則を文書化する必要があるだけです。
関数の呼び出し規約を指定します。呼び出し規約は、パラメーターが関数に渡される方法の一連のルールです。アドレスごとまたはコピーごとの順序、パラメーターをクリーンアップするのは誰 (呼び出し元または呼び出し先) などです。
__stdcall は、呼び出し規則を示します (詳細については、この PDFを参照してください)。これは、関数の引数がスタックからプッシュおよびポップされる方法と、責任者を指定することを意味します。
__stdcall は、いくつかの呼び出し規則の 1 つにすぎず、WINAPI 全体で使用されます。これらの関数の一部のコールバックとして関数ポインターを提供する場合は、これを使用する必要があります。一般に、コードで特定の呼び出し規則を示す必要はありませんが、上記の場合 (サードパーティ コードへのコールバックを提供する) を除いて、コンパイラの既定値を使用するだけです。
これは、WinAPI 関数を適切に呼び出す必要がある呼び出し規約です。呼び出し規約は、パラメーターが関数に渡される方法と戻り値が関数から渡される方法に関する一連の規則です。
呼び出し元と呼び出されたコードが異なる規則を使用している場合、未定義の動作が発生します (奇妙に見える crash など)。
C++ コンパイラは、デフォルトでは __stdcall を使用しません。他の規則を使用します。そのため、C++ から WinAPI 関数を呼び出すには、__stdcall を使用するように指定する必要があります。これは通常、Windoes SDK ヘッダー ファイルで行われ、関数ポインターを宣言するときにも行います。
関数を呼び出すと、スタック/レジスタにロードされます。__stdcallは1つの規則/方法(最初に右引数、次に左引数...)であり、__declはスタックまたはレジスタに関数をロードするために使用される別の規則です。
それらを使用する場合は、リンク中に関数をロード/アンロードするためにその特定の方法を使用するようにコンピューターに指示するため、不一致/クラッシュは発生しません。
そうしないと、function-calleeとfunction-callerが異なる規則を使用して、プログラムがクラッシュする可能性があります。