【C++】C++でDLLを作るときに書くdeclspecとかstdcallについて~defファイルまで

C++でDLLを作るときに書くdeclspecとかstdcallとかについて調べたメモです。
最終的にdefファイル化するところまでの流れをまとめました。

昨日書いた下記の記事ではこの辺りにあまり触れなかったので改めてまとめます。

light11.hatenadiary.com

C++でDLLを作るときの関数の書き方

C++でDLLを作るとき、外部公開用の関数は次のように記述する必要があります。

#include "stdafx.h"

extern "C" __declspec(dllexport) int __stdcall Example();

extern "C" __declspec(dllexport) int __stdcall Example()
{
    return 5;
}

うーん長いしわけがわかりません。
ひとまず一つずつ調べていきます。

extern "C"

C++オーバーロードやクラスといった概念がある関係で
ビルド時に関数名が変えられて結果的に関数が見つからなくなってしまいます。

extern "C"キーワードはこれを防ぐために記述するようです。

www.wagavulin.jp

__stdcall

__stdcallは呼び出し規約を指定するキーワードです。
呼び出し規約とは、ざっくり言うと関数における引数の処理のルールのことのようです。

konuma.org

要は、C#C++は違う言語で違う処理の仕方をしているので、処理のルールを決めなきゃいけないよねって話です。
そのルールが__stdcallです。
__stdcall以外にもあるようですが、とりあえずは__stdcallと書いとけばよさそうです。

__declspec(dllexport)

__declspec(dllexport)は外部から参照する関数に付けるキーワードです。
これは後述するdefファイルを定義する場合には書く必要がなくなります。

マクロ化

関数を定義するたびにいちいちexternやらdeclspecやら書いてられないので、普通はマクロを定義するようです。

#include "stdafx.h"

#define DLLEXPORT extern "C" __declspec(dllexport)

DLLEXPORT int __stdcall Example();

DLLEXPORT int __stdcall Example()
{
    return 5;
}

これでだいぶ簡潔に書けるようになりました。

defファイル

ちなみに、__declspec(dllexport)キーワードはdefファイルというファイルを作ることで記述が不要になります。

rokujo.hatenadiary.com

defファイルを作るにはまず、ソリューションエクスプローラー > プロジェクト名 > 追加 > 新しい項目 を選択します。

f:id:halya_11:20190303202744p:plain

次にVisual C++ > コード > モジュール定義ファイルを選択します。 プロジェクト名と同じ命名でdefファイルを作成します。

f:id:halya_11:20190303202958p:plain

作成したdefファイルに次のように記述します。

LIBRARY ExampleDll
EXPORTS
    Example @1

ライブラリ名と関数名を指定しています。
@以下の数字は連番です。

ソースコードからは次のように__declspec(dllexport)キーワードを削除できます。

#include "stdafx.h"

#define DLLEXPORT extern "C"

DLLEXPORT int __stdcall Example();

DLLEXPORT int __stdcall Example()
{
    return 5;
}

ただマクロ化している部分の記述が減るだけなのでdefファイルをわざわざ定義しないほうがお手軽ではあるかもしれません。その辺りはお好みで。

参考

blog.northcol.org

www.wagavulin.jp

konuma.org

www.ne.jp

関連

light11.hatenadiary.com