Visual Studio 2017
How to Create New DLL Project with Visual Studio 2017 Professional Update 2
2017.10.07: created by
目次へ
[お知らせ]
Microsoft の "Developer Network (日本語)" で
"プロジェクト名_EXPORTS"定数の未定義について指摘した
ところ、日曜日(2017.10.08)の朝だというのに40分未満で適切な内容の返信が投稿され、
Microsfotの開発チームへの報告
が動画付きで上がりました。優秀な技術者、恐るべし。
Visual Studio 2017 Update 2 で DLLプロジェクトを新たに作成する手順
- ファイル -> 新規作成 -> プロジェクト-> Visual C++ -> Windows デスクトップ -> Windows デスクトップウィザード を選択します。
プロジェクトの名前を入力してから、"OK" を選択します。
- 「アプリケーションの設定」で「アプリケーションの種類」を
「ダイナミックリンクライブラリ(.dll)」に,
追加のオプションの「シンボルのエクスポート」をチェックします。
Visual Studio 2017 Update 2 (version 15.3.5) で DLL の ビルド時に "dllimport ..." エラーが起きたら
[注意] このバグは Oct/11/2017 にリリースされた Visual Studio 2017 version 15.4 で解決されています。
DLL のプロジェクトには "プロジェクト名.h" と "プロジェクト名.cpp"
というファイルが含まれています。これらを Example.h と Example.cpp として説明します。
- Example.h と Example.cpp の初期状態は次のようになっています。
Example.h |
#ifdef EXAMPLE_EXPORTS
#define EXAMPLE_API __declspec(dllexport)
#else
#define EXAMPLE_API __declspec(dllimport)
#endif
class EXAMPLE_API CExample {
public:
CExample(void);
};
extern EXAMPLE_API int nExample;
EXAMPLE_API int fnExample(void);
|
Example.cpp (初期状態) |
#include "stdafx.h"
#include "Example.h"
EXAMPLE_API int nExample=0;
EXAMPLE_API int fnExample(void)
{
return 42;
}
CExample::CExample()
{
return;
}
|
-
Example.h は、 次のどちらのどちらの場合でも利用されます。
[1]Example.cpp をコンパイルして Example.dll を作る時
[2]Example.dll を利用するプログラムをコンパイルする時
[1]の場合は、Visual Studio が
EXAMPLE_EXPORTS
を定義してコンパイルするので、Example.cpp の
EXAMPLE_API は
__declspec(dllexport)
として扱われます。
[2]の場合は、
EXAMPLE_EXPORTS
が定義されない状態でコンパイルするので、
Example.h の中の
EXAMPLE_API
は
__declspec(dllimport)
として扱われます。
すなわち、[1], [2] どちらの場合でも同じ Example.h が使えるという便利な状況になっているわけです。
- ところが Visual Studio 2017 Professional Update 2 においては、
[1]の場合でも
EXAMPLE_EXPORTS
を定義せずにコンパイルするというバグがあるようです。
- このバグを避けるには、
Example.cpp の中で Example.h をinclude するよりも前に、
「もしも
EXAMPLE_EXPORTS
が定義されていなければ定義する」
という記述をします。
Example.cpp (バグ対処後) |
#include "stdafx.h"
#ifndef EXAMPLE_EXPORTS
#define EXAMPLE_EXPORTS
#endif
#include "Example.h"
EXAMPLE_API int nExample=0;
EXAMPLE_API int fnExample(void)
{
return 42;
}
CExample::CExample()
{
return;
}
|
- 定義すべき定数名は "プロジェクト名_EXPORTS" となります。
上の例ではプロジェクト名が Example だったので EXAMPLE_EXPORTS という定数でした。
自分のプロジェクト名に読み替えて、対処して下さい。
http://nw.tsuda.ac.jp/