DLL 関数の Visual Basic アプリケーションからの呼び出し方
Visual Basic アプリケーション (や Pascal、Fortran などの他の言語で書かれたアプリケーション) から C/C++ DLL 内の関数を呼び出すには、正しい呼び出し規則を使い、コンパイラによって名前装飾されずに、エクスポートされる必要があります。
__stdcall
は、関数の正しい呼び出し規則を作成します。つまり、呼び出された関数がスタックをクリアし、パラメーターは右から左へ渡されます。ただし、関数名は異なる方法で装飾されます。 このため、__declspec(dllexport)
が DLL 内のエクスポート関数で使用される場合は、装飾名がエクスポートされます。
__stdcall
で装飾された名前には、シンボル名の前にアンダースコア ( _ ) が付けられ、シンボルの後にはアット マーク (@) が付けられ、その後に引数リストのバイト数 (必要なスタック空間) が付けられます。 結果として、宣言時の関数は次のようになります。
int __stdcall func (int a, double b)
は、出力の _func@12
として修飾されます。
C の呼び出し規則 (__cdecl
) による装飾では、名前は _func
となります。
装飾名を取得するには、/MAP を使用します。 __declspec(dllexport)
を使用すると、次の処理が行われます。
関数が C の呼び出し規則 (
__cdecl
) を使用してエクスポートされる場合、先頭のアンダースコア ( _ ) は名前のエクスポート時に除去されます。エクスポートされる関数が C の呼び出し規則を使わない場合 (
__stdcall
など) は、装飾名がエクスポートされます。
スタックがクリアされた場所をオーバーライドする方法はないので、__stdcall
を使う必要があります。 __stdcall
を使って装飾を外すには、.def ファイルの EXPORTS セクションのエイリアスを使って、その名前を指定する必要があります。 関数宣言の例を次に示します。
int __stdcall MyFunc (int a, double b);
void __stdcall InitCode (void);
.DEF ファイルの内容は、次のとおりです。
EXPORTS
MYFUNC=_MyFunc@12
INITCODE=_InitCode@0
Visual Basic で書かれたプログラムから DLL を呼び出す場合は、ここで示したエイリアスの手法を .def ファイル内で使用する必要があります。 エイリアスが Visual Basic プログラムの中で宣言されている場合は、.def ファイル内でのエイリアスは不要です。 これは、Visual Basic プログラムでは、Declare ステートメントにエイリアス句を追加することで実現されます。