Visual Studio 2017

How to Create New DLL Project with Visual Studio 2017 Professional Update 2


2017.10.07: created by
Japanese English
目次へ

[お知らせ] Microsoft の "Developer Network (日本語)" で "プロジェクト名_EXPORTS"定数の未定義について指摘した ところ、日曜日(2017.10.08)の朝だというのに40分未満で適切な内容の返信が投稿され、 Microsfotの開発チームへの報告 が動画付きで上がりました。優秀な技術者、恐るべし。


Visual Studio 2017 Update 2 で DLLプロジェクトを新たに作成する手順

  1. ファイル -> 新規作成 -> プロジェクト-> Visual C++ -> Windows デスクトップ -> Windows デスクトップウィザード を選択します。






  2. プロジェクトの名前を入力してから、"OK" を選択します。

  3. 「アプリケーションの設定」で「アプリケーションの種類」を 「ダイナミックリンクライブラリ(.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 として説明します。

  1. Example.h と Example.cpp の初期状態は次のようになっています。
  2. 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;
    }
    
    
  3. Example.h は、 次のどちらのどちらの場合でも利用されます。
      [1]Example.cpp をコンパイルして Example.dll を作る時
      [2]Example.dll を利用するプログラムをコンパイルする時
  4. [1]の場合は、Visual Studio が EXAMPLE_EXPORTS を定義してコンパイルするので、Example.cpp の EXAMPLE_API は __declspec(dllexport) として扱われます。

    [2]の場合は、 EXAMPLE_EXPORTS が定義されない状態でコンパイルするので、 Example.h の中の EXAMPLE_API は __declspec(dllimport) として扱われます。

    すなわち、[1], [2] どちらの場合でも同じ Example.h が使えるという便利な状況になっているわけです。

  5. ところが Visual Studio 2017 Professional Update 2 においては、 [1]の場合でも EXAMPLE_EXPORTS を定義せずにコンパイルするというバグがあるようです。
  6. このバグを避けるには、 Example.cpp の中で Example.h をinclude するよりも前に、 「もしも EXAMPLE_EXPORTS が定義されていなければ定義する」 という記述をします。
  7. 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;
    }
    
    
  8. 定義すべき定数名は "プロジェクト名_EXPORTS" となります。 上の例ではプロジェクト名が Example だったので EXAMPLE_EXPORTS という定数でした。 自分のプロジェクト名に読み替えて、対処して下さい。


http://nw.tsuda.ac.jp/