Visual C/C++コンパイラの呼出し規則について

|

CPUがx64だと言っても、まだまだx86の呼出し規則が優勢と言うかWOW64の方が全盛の内に、x86呼出し規則を浚ってみました。

C・C++間や他言語からのDLL内関数呼出しを行う場合、大事なのはCリンケージと __stdcall です。

特に指定しない限り、C++コンパイラはC++リンケージであるC++のタイプセーフな名前付け規約(名前装飾)と、C++の呼出し規則を使用します。

Cコンパイラは既定で、Cの呼出し規則とCリンケージを使います。

★C・C++間でDLL内の関数を利用するには、Cリンケージである extern "C" を指定して関数を宣言し、コンパイラがC++の関数名を装飾するのを禁止する必要があります。

★他言語からDLL内の関数を利用するには、__stdcall 呼出し規則を使用する必要があります。


<注意点>

・C++が装飾名を必須とするのは、オーバーロードされた関数、クラスや名前空間のメンバー、コンストラクターやデストラクター、などなどを一意に特定する必要がある事に起因します。

・__stdcall で修飾さる名前には、関数名の前にアンダースコア '_' が、後にアットマーク '@' が、更にその後に引数リストのバイト数が付けられます。例えば、int __stdcall func(int a, double b) 関数は、_func@12 と名前修飾されます。


【Visual C/C++ コンパイラの呼出し規則】

Visual C/C++ コンパイラの呼出し規則一覧
規約 *1コンパイラ
オプション
スタック
一掃
引数渡しCリンケージ
修飾形式 *2
補足
__cdecl /Gd
x86 のみ
呼出し元 右から左の順で
スタックに積まれる
_fname C/C++標準
__clrcall なし N/A 左から右の順で
CLR式スタックに収容
N/A .NET専用
__stdcall /Gz
x86 のみ
呼出し先 右から左の順で
スタックに積まれる
_fname@num Win32API呼出し
他言語アプリからの
関数呼び出し
__fastcall /Gr
x86 のみ
呼出し先 レジスタで渡され
残りは右から左の順で
スタックに積まれる
@fname@num 通常、高速呼出し
__thiscall なし 呼出し先 右から左の順でスタック
に積まれ this ポインタは
ECX レジスタに格納
N/A C++メンバー関数
__vectorcall /Gv
x86, x64
呼出し先 レジスタで渡され
残りは右から左の順で
スタックに積まれる
fname@@num __fastcall より多くの
レジスタで渡すか
既定の x64 呼出し *3
を使う

 *1:Visual C/C++ コンパイラでサポートされている呼び出し規約
 *2:fname は関数名、num は引数リストのバイト数を表す
 *3:x64ABIの既定では4レジスタ高速呼出しの呼び出し規則が使用される

このブログ記事について

このページは、微禄が2021年7月15日 06:52に書いたブログ記事です。

ひとつ前のブログ記事は「VisualBasicのDllImportを使ってWindowsAPIを呼び出す」です。

次のブログ記事は「32ビットOS下のVisualBasicからGetSystemInfo関数を呼び出す」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

NOP法人 アジアチャイルドサポート 最も大切なボランティアは、自分自身が一生懸命に生きること