次の方法で共有


チュートリアル: 独自のダイナミック リンク ライブラリを作成して使用する (C++)

このチュートリアルでは、Visual Studio IDE を使用して、Microsoft C++ (MSVC) で記述された独自のダイナミック リンク ライブラリ (DLL) を作成する方法と、別の C++ アプリから DLL を使用する方法について説明します。 DLL は、UNIX ベースのオペレーティング システムの 共有ライブラリ とも呼ばれ、最も便利な種類の Windows コンポーネントの 1 つです。 これらを使用して、コードとリソースを共有したり、アプリのサイズを縮小したりできます。 DLL を使用すると、アプリの保守と拡張を容易にすることもできます。

このチュートリアルでは、いくつかの数学関数を実装する DLL を作成します。 次に、DLL の関数を使用するコンソール アプリを作成します。 また、Windows DLL で使用されるプログラミング手法と規則の一部を紹介します。

このチュートリアルでは、次の手順について説明します。

  • Visual Studio で DLL プロジェクトを作成します。
  • エクスポートされた関数と変数を DLL に追加します。
  • Visual Studio でコンソール アプリ プロジェクトを作成します。
  • コンソール アプリで DLL からインポートされた関数と変数を使用します。
  • 完成したアプリを実行します。

静的にリンクされたライブラリと同様に、DLL は変数、関数、およびリソースを名前で エクスポート します。 クライアント アプリ は、 これらの変数、関数、およびリソースを使用するために名前をインポートします。 静的にリンクされたライブラリとは異なり、Windows はアプリ内のインポートを、リンク時に接続するのではなく、読み込み時または実行時に DLL 内のエクスポートに接続します。 Windows では、これらの接続を行うために、標準の C++ コンパイル モデルの一部ではない追加情報が必要です。 MSVC コンパイラは、この追加情報を提供するために、Microsoft 固有の C++ 拡張機能をいくつか実装します。 これらの拡張機能について説明します。

このチュートリアルでは、2 つの Visual Studio ソリューションを作成します。1 つは DLL をビルドし、1 つはクライアント アプリをビルドします。 DLL は C 呼び出し規約を使用します。 プラットフォーム、呼び出し規則、およびリンク規則が一致している限り、他のプログラミング言語で記述されたアプリから呼び出すことができます。 クライアント アプリは 暗黙的なリンクを使用します。Windows は読み込み時にアプリを DLL にリンクします。 このリンクにより、アプリは静的にリンクされたライブラリ内の関数と同様に、DLL で提供される関数を呼び出すことができます。

このチュートリアルでは、一般的な状況については説明しません。 このコードでは、他のプログラミング言語による C++ DLL の使用は示されていません。 リソースのみの DLL を作成する方法や、明示的なリンクを使用して読み込み時ではなく実行時に DLL を読み込む方法は示されていません。 MSVC と Visual Studio を使用して、これらすべての操作を行うことができます。

DLL のコードは C++ で記述されていますが、エクスポートされた関数には C スタイルのインターフェイスを使用します。 これには主に 2 つの理由があります。最初に、他の多くの言語で C スタイル関数のインポートがサポートされています。 クライアント アプリを C++ で記述する必要はありません。 次に、エクスポートされたクラスとメンバー関数に関連するいくつかの一般的な落とし穴を回避します。 クラス宣言内で参照されるすべてのインスタンス化もエクスポートする必要があるため、クラスをエクスポートするときに診断が困難なエラーを発生させるのは簡単です。 この制限は DLL には適用されますが、静的ライブラリには適用されません。 クラスがプレーンな古いデータ スタイルの場合は、この問題に陥ってはいけません。

DLL の詳細については、「 Visual Studio での C/C++ DLL の作成」を参照してください。 暗黙的なリンクと明示的なリンクの詳細については、「 使用するリンク方法を決定する」を参照してください。 C 言語リンケージ規則を使用するプログラミング言語で使用する C++ DLL の作成については、C 言語実行可能ファイルで使用する C++ 関数のエクスポートを参照してください。 .NET 言語で使用する DLL を作成する方法については、「 Visual Basic アプリケーションから DLL 関数を呼び出す」を参照してください。

[前提条件]

  • Microsoft Windows 7 以降。 最適な開発エクスペリエンスを実現するために、最新バージョンの Windows をお勧めします。
  • Visual Studio。 Visual Studio をダウンロードしてインストールする方法については、「 Visual Studio のインストール」を参照してください。 インストーラーを実行するときは、 C++ によるデスクトップ開発 ワークロードがチェックされていることを確認します。 Visual Studio をインストールしたときにこのワークロードをインストールしなかった場合は、心配しないでください。 インストーラーをもう一度実行して、今すぐインストールできます。

    Visual Studio インストーラー、C++ ワークロードを使用したデスクトップ開発のスクリーンショット。

  • Visual Studio。 Visual Studio 2015 をダウンロードしてインストールする方法については、「 Visual Studio 2015 のインストール」を参照してください。 既定ではインストールされないため、 カスタム インストールを使用して C++ コンパイラとツールをインストールします。
  • Visual Studio IDE の使用の基本について説明します。 以前に Windows デスクトップ アプリを使用したことがある場合は、おそらく追いつくことができます。 概要については、 Visual Studio IDE の機能ツアーを参照してください。

  • C++ 言語に関する知識。 心配しないで、私たちはあまりにも複雑なことをしません。

このチュートリアルでは、Visual Studio 2017 バージョン 15.9 以降を使用していることを前提としています。 Visual Studio 2017 の一部の以前のバージョンでは、コード テンプレートに問題があったか、別のユーザー インターフェイス ダイアログが使用されていました。 問題を回避するには、Visual Studio インストーラーを使用して Visual Studio 2017 をバージョン 15.9 以降に更新します。

DLL プロジェクトを作成する

次の一連のタスクでは、DLL のプロジェクトを作成し、コードを追加してビルドします。 開始するには、Visual Studio IDE を起動し、必要に応じてサインインします。 この手順は、使用している Visual Studio のバージョンによって若干異なります。 Visual Studio の優先バージョンの手順を確認するには、このページの目次の上部にある バージョン セレクターを使用します。

Visual Studio で DLL プロジェクトを作成するには

  1. メニューバーで、 [ファイル]>[新規作成]>[プロジェクト] の順に選択して、 [新しいプロジェクトの作成] ダイアログ ボックスを開きます。

    ダイナミック リンク ライブラリ テンプレートが強調表示されている [新しいプロジェクトの作成] ダイアログ ボックスのスクリーンショット。

  2. ダイアログの上部で、[ 言語 ] を [C++] に設定し、[ プラットフォーム ] を [Windows] に設定し、[ プロジェクトの種類][ライブラリ] に設定します。

  3. フィルター処理されたプロジェクトの種類の一覧で、[ ダイナミック リンク ライブラリ (DLL)]、[ 次へ] の順に選択します。

  4. [新しいプロジェクトの構成] ページで、[プロジェクト名] ボックスに「MathLibrary」と入力して、プロジェクトの名前を指定します。 既定の [場所 ] と [ソリューション名] の 値のままにします。 [ソリューション] を [新しいソリューションの作成] に設定します。 オンになっている場合は、[ ソリューションとプロジェクトを同じディレクトリに配置 する] チェック ボックスをオフにします。

  5. [作成] ボタンをクリックしてプロジェクトを作成します。

ソリューションが作成されると、生成されたプロジェクト ファイルとソース ファイルが Visual Studio の ソリューション エクスプローラー ウィンドウに表示されます。

MathLibrary プロジェクトが強調表示されている [ソリューション エクスプローラー] ウィンドウのスクリーンショット。

Visual Studio 2017 で DLL プロジェクトを作成するには

  1. メニューバーで、[ファイル]>[新規作成]>[プロジェクト] の順に選択して、[新しいプロジェクト] ダイアログ ボックスを開きます。

  2. [ 新しいプロジェクト ] ダイアログ ボックスの左側のウィンドウで、[ インストール済み>Visual C++>Windows デスクトップ] を選択します。 中央のウィンドウで、[ Dynamic-Link ライブラリ (DLL) を選択します。 プロジェクトの名前を指定するには、[名前] ボックスに「MathLibrary」と入力します。 既定の [場所 ] と [ソリューション名] の 値のままにします。 [ソリューション] を [新しいソリューションの作成] に設定します。 オフになっている場合は、[ ソリューションのディレクトリの作成 ] をオンにします。

    Visual Studio 2017 の [新しいプロジェクト] ダイアログ ボックスのスクリーンショット。[名前] テキスト ボックスに数学ライブラリが表示されています。

  3. [ OK] ボタンをクリックしてプロジェクトを作成します。

ソリューションが作成されると、生成されたプロジェクト ファイルとソース ファイルが Visual Studio の ソリューション エクスプローラー ウィンドウに表示されます。

Visual Studio 2017 の [ソリューション エクスプローラー] ウィンドウのスクリーンショット。数学ライブラリが強調表示されています。

Visual Studio 2015 以前のバージョンで DLL プロジェクトを作成するには

  1. メニュー バーで、 [ファイル]>[新規作成]>[プロジェクト] を選択します。

  2. [ 新しいプロジェクト ] ダイアログ ボックスの左側のウィンドウで、[ インストール済み>テンプレート] を展開し、[ Visual C++] を選択し、中央のウィンドウで [Win32 コンソール アプリケーション] を選択します。 [名前] 編集ボックスに「MathLibraryと入力して、プロジェクトの名前を指定します。 既定の [場所 ] と [ソリューション名] の 値のままにします。 [ソリューション] を [新しいソリューションの作成] に設定します。 オフになっている場合は、[ ソリューションのディレクトリの作成 ] をオンにします。

    Visual Studio 2015 の [新しいプロジェクト] ダイアログ ボックスのスクリーンショット。[名前] テキスト ボックスに MathLibrary が表示されています。

  3. [ OK ] ボタンを選択して [新しいプロジェクト ] ダイアログを閉じ、 Win32 アプリケーション ウィザードを起動します。

    Win32 アプリケーション ウィザードの [概要] ページのスクリーンショット。

  4. [次へ] ボタンをクリックします。 [ アプリケーションの設定] ページの [ アプリケーションの種類] で、[ DLL] を選択します。

    Win32 アプリケーション ウィザードの [アプリケーション設定] ページのスクリーンショット。

  5. [ 完了 ] ボタンを選択してプロジェクトを作成します。

ウィザードがソリューションを完了すると、Visual Studio の ソリューション エクスプローラー ウィンドウに生成されたプロジェクトファイルとソース ファイルが表示されます。

Visual Studio 2015 の [ソリューション エクスプローラー] ウィンドウのスクリーンショット。MathLibrary が強調表示されています。

現時点では、この DLL はあまり実行されません。 次に、DLL がエクスポートする関数を宣言するヘッダー ファイルを作成し、DLL に関数定義を追加して、より便利にします。

DLL にヘッダー ファイルを追加するには

  1. 関数のヘッダー ファイルを作成するには、メニュー バーの [プロジェクト] > [新しい項目の追加] を選択します。

  2. [ 新しい項目の追加 ] ダイアログ ボックスの左側のウィンドウで、 Visual C++ を選択します。 中央のウィンドウで、[ ヘッダー ファイル (.h)] を選択します。 ヘッダー ファイルの名前として MathLibrary.h を指定します。

    [新しい項目の追加] ダイアログのスクリーンショット。C + ヘッダー ファイル テンプレートが選択され、[名前] ボックスに MathLibrary.h が入力されています。

  3. [ 追加 ] ボタンを選択すると、新しいエディター ウィンドウに表示される空白のヘッダー ファイルが生成されます。

    エディターの空の MathLibrary.h ファイルのスクリーンショット。

  4. ヘッダー ファイルの内容を次のコードに置き換えます。

    // MathLibrary.h - Contains declarations of math functions
    #pragma once
    
    #ifdef MATHLIBRARY_EXPORTS
    #define MATHLIBRARY_API __declspec(dllexport)
    #else
    #define MATHLIBRARY_API __declspec(dllimport)
    #endif
    
    // The Fibonacci recurrence relation describes a sequence F
    // where F(n) is { n = 0, a
    //               { n = 1, b
    //               { n > 1, F(n-2) + F(n-1)
    // for some initial integral values a and b.
    // If the sequence is initialized F(0) = 1, F(1) = 1,
    // then this relation produces the well-known Fibonacci
    // sequence: 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
    
    // Initialize a Fibonacci relation sequence
    // such that F(0) = a, F(1) = b.
    // This function must be called before any other function.
    extern "C" MATHLIBRARY_API void fibonacci_init(
        const unsigned long long a, const unsigned long long b);
    
    // Produce the next value in the sequence.
    // Returns true on success and updates current value and index;
    // false on overflow, leaves current value and index unchanged.
    extern "C" MATHLIBRARY_API bool fibonacci_next();
    
    // Get the current value in the sequence.
    extern "C" MATHLIBRARY_API unsigned long long fibonacci_current();
    
    // Get the position of the current value in the sequence.
    extern "C" MATHLIBRARY_API unsigned fibonacci_index();
    

このヘッダー ファイルは、2 つの初期値を指定して、一般化されたフィボナッチ シーケンスを生成するいくつかの関数を宣言します。 fibonacci_init(1, 1)を呼び出すと、使い慣れたフィボナッチ数列が生成されます。

ファイルの先頭にあるプリプロセッサ ステートメントに注目してください。 DLL プロジェクトの新しいプロジェクト テンプレートは、定義されたプリプロセッサ マクロに <PROJECTNAME>_EXPORTS を追加します。 この例では、Visual Studio は MathLibrary DLL プロジェクトのビルド時に MATHLIBRARY_EXPORTS を定義します。

MATHLIBRARY_EXPORTS マクロが定義されている場合、MATHLIBRARY_API マクロは、関数宣言の__declspec(dllexport)修飾子を設定します。 この修飾子は、他のアプリケーションで使用するために DLL から関数または変数をエクスポートするようにコンパイラとリンカーに指示します。 MATHLIBRARY_EXPORTSが未定義の場合 (たとえば、クライアント アプリケーションによってヘッダー ファイルが含まれている場合)、MATHLIBRARY_API__declspec(dllimport)修飾子を宣言に適用します。 この修飾子は、アプリケーション内の関数または変数のインポートを最適化します。 詳細については、「dllexport、dllimport」をご覧ください。

DLL に実装を追加するには

  1. ソリューション エクスプローラーで、[ソース ファイル] ノードを右クリックし、[追加>新しい項目] を選択します。 前の手順で新しいヘッダー ファイルを追加したのと同じ方法で、.cppという名前の新しいMathLibrary.cpp ファイルを作成します。

  2. エディター ウィンドウで、[ MathLibrary.cpp ] タブが既に開いている場合は選択します。 そうでない場合は、ソリューション エクスプローラーMathLibrary.cpp プロジェクトのソース ファイル フォルダーのをダブルクリックして開きます。

  3. エディターで、 MathLibrary.cpp ファイルの内容を次のコードに置き換えます。

    // MathLibrary.cpp : Defines the exported functions for the DLL.
    #include "pch.h" // use stdafx.h in Visual Studio 2017 and earlier
    #include <utility>
    #include <limits.h>
    #include "MathLibrary.h"
    
    // DLL internal state variables:
    static unsigned long long previous_;  // Previous value, if any
    static unsigned long long current_;   // Current sequence value
    static unsigned index_;               // Current seq. position
    
    // Initialize a Fibonacci relation sequence
    // such that F(0) = a, F(1) = b.
    // This function must be called before any other function.
    void fibonacci_init(
        const unsigned long long a,
        const unsigned long long b)
    {
        index_ = 0;
        current_ = a;
        previous_ = b; // see special case when initialized
    }
    
    // Produce the next value in the sequence.
    // Returns true on success, false on overflow.
    bool fibonacci_next()
    {
        // check to see if we'd overflow result or position
        if ((ULLONG_MAX - previous_ < current_) ||
            (UINT_MAX == index_))
        {
            return false;
        }
    
        // Special case when index == 0, just return b value
        if (index_ > 0)
        {
            // otherwise, calculate next sequence value
            previous_ += current_;
        }
        std::swap(current_, previous_);
        ++index_;
        return true;
    }
    
    // Get the current value in the sequence.
    unsigned long long fibonacci_current()
    {
        return current_;
    }
    
    // Get the current index position in the sequence.
    unsigned fibonacci_index()
    {
        return index_;
    }
    
  1. エディター ウィンドウで、既に開いている 場合は、MathLibrary.cpp のタブを選択します。 そうでない場合は、ソリューション エクスプローラーMathLibrary プロジェクトのソース ファイル フォルダーのMathLibrary.cppをダブルクリックして開きます。

  2. エディターで、 MathLibrary.cpp ファイルの内容を次のコードに置き換えます。

    // MathLibrary.cpp : Defines the exported functions for the DLL.
    #include "stdafx.h" // use pch.h in Visual Studio 2019 and later
    #include <utility>
    #include <limits.h>
    #include "MathLibrary.h"
    
    // DLL internal state variables:
    static unsigned long long previous_;  // Previous value, if any
    static unsigned long long current_;   // Current sequence value
    static unsigned index_;               // Current seq. position
    
    // Initialize a Fibonacci relation sequence
    // such that F(0) = a, F(1) = b.
    // This function must be called before any other function.
    void fibonacci_init(
        const unsigned long long a,
        const unsigned long long b)
    {
        index_ = 0;
        current_ = a;
        previous_ = b; // see special case when initialized
    }
    
    // Produce the next value in the sequence.
    // Returns true on success, false on overflow.
    bool fibonacci_next()
    {
        // check to see if we'd overflow result or position
        if ((ULLONG_MAX - previous_ < current_) ||
            (UINT_MAX == index_))
        {
            return false;
        }
    
        // Special case when index == 0, just return b value
        if (index_ > 0)
        {
            // otherwise, calculate next sequence value
            previous_ += current_;
        }
        std::swap(current_, previous_);
        ++index_;
        return true;
    }
    
    // Get the current value in the sequence.
    unsigned long long fibonacci_current()
    {
        return current_;
    }
    
    // Get the current index position in the sequence.
    unsigned fibonacci_index()
    {
        return index_;
    }
    

これまでにすべてが機能することを確認するには、DLL をコンパイルします。 コンパイルするには、メニュー バーの [Build>Build Solution ] を選択します。 DLL と関連するコンパイラ出力は、ソリューション フォルダーのすぐ下にある Debug というフォルダーに配置されます。 リリース ビルドを作成すると、出力は Release という名前のフォルダーに配置されます。 出力は次のようになります。

1>------ Build started: Project: MathLibrary, Configuration: Debug Win32 ------
1>pch.cpp
1>dllmain.cpp
1>MathLibrary.cpp
1>Generating Code...
1>   Creating library C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.lib and object C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.exp
1>MathLibrary.vcxproj -> C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.dll
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
1>------ Build started: Project: MathLibrary, Configuration: Debug Win32 ------
1>stdafx.cpp
1>dllmain.cpp
1>MathLibrary.cpp
1>Generating Code...
1>   Creating library C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.lib and object C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.exp
1>MathLibrary.vcxproj -> C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.dll
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
1>------ Build started: Project: MathLibrary, Configuration: Debug Win32 ------
1>MathLibrary.cpp
1>dllmain.cpp
1>Generating Code...
1>   Creating library C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.lib and object C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.exp
1>MathLibrary.vcxproj -> C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.dll
1>MathLibrary.vcxproj -> C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.pdb (Partial PDB)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

これで、Visual Studio を使用して DLL が作成されました。 次に、DLL によってエクスポートされた関数を使用するクライアント アプリを作成します。

DLL を使用するクライアント アプリを作成する

DLL を作成するときは、クライアント アプリで DLL を使用する方法を検討してください。 関数を呼び出すか、DLL によってエクスポートされたデータにアクセスするには、クライアント のソース コードにコンパイル時に使用可能な宣言が必要です。 リンク時に、リンカーは関数呼び出しまたはデータ アクセスを解決するための情報を必要とします。 DLL は、インポート ライブラリにこの情報を提供します。このファイルには、実際のコードではなく、関数とデータを検索する方法に関する情報が含まれています。 実行時には、オペレーティング システムが見つけることができる場所で、クライアントが DLL を使用できる必要があります。

独自のものでもサードパーティのものでも、クライアント アプリ プロジェクトでは DLL を使用するために複数の情報が必要です。 DLL エクスポートを宣言するヘッダー、リンカーのインポート ライブラリ、および DLL 自体を検索する必要があります。 1 つの解決策は、これらのファイルをすべてクライアント プロジェクトにコピーすることです。 クライアントの開発中に変更される可能性が低いサードパーティの DLL の場合、この方法が最適な方法である可能性があります。 ただし、DLL もビルドする場合は、重複を回避することをお勧めします。 開発中の DLL ファイルのローカル コピーを作成した場合、あるコピーではヘッダー ファイルを誤って変更したが、もう一方のコピーでは変更しない場合や、古いライブラリを使用する可能性があります。

同期外のコードを回避するには、DLL プロジェクトから直接 DLL ヘッダー ファイルを含むようにクライアント プロジェクトにインクルード パスを設定することをお勧めします。 また、クライアント プロジェクトのライブラリ パスを設定して、DLL プロジェクトから DLL インポート ライブラリを含めます。 最後に、ビルドされた DLL を DLL プロジェクトからクライアント ビルド出力ディレクトリにコピーします。 この手順により、クライアント アプリでビルドしたのと同じ DLL コードを使用できます。

Visual Studio でクライアント アプリを作成するには

  1. メニュー バーで、[ ファイル>新規作成>プロジェクト を選択して、[ 新しいプロジェクトの作成 ] ダイアログ ボックスを開きます。

  2. ダイアログの上部で、[言語][C++] に、[プラットフォーム][Windows] に、[プロジェクト タイプ][コンソール] に設定します。

  3. フィルター処理されたプロジェクト タイプの一覧から、 [コンソール アプリ] を選択して、 [次へ] を選択します。

  4. [新しいプロジェクトの構成] ページで、[プロジェクト名] ボックスに「MathClient」と入力して、プロジェクトの名前を指定します。 既定の [場所 ] と [ソリューション名] の 値のままにします。 [ソリューション] を [新しいソリューションの作成] に設定します。 オンになっている場合は、[ ソリューションとプロジェクトを同じディレクトリに配置 する] チェック ボックスをオフにします。

    [コンソール アプリ] オプションが強調表示されている [新しいプロジェクトの作成] ダイアログ ボックスのスクリーンショット。

  5. [作成] ボタンを選択してクライアント プロジェクトを作成します。

最小限のコンソール アプリケーション プロジェクトが自動的に作成されます。 メイン ソース ファイルの名前は、前に入力したプロジェクト名と同じです。 この例では、 MathClient.cppという名前です。 ビルドすることはできますが、DLL はまだ使用されていません。

Visual Studio 2017 でクライアント アプリを作成するには

  1. 作成した DLL を使用する C++ アプリを作成するには、メニュー バーの [ ファイル>New>Project] を選択します。

  2. [新しいプロジェクト] ダイアログの左側のウィンドウで、[インストール済み>] の下の [Windows デスクトップ] を選択します。 中央のウィンドウで、[ Windows コンソール アプリケーション] を選択します。 [名前] 編集ボックスに、プロジェクトの名前 MathClient 指定します。 既定の [場所 ] と [ソリューション名] の 値のままにします。 [ソリューション] を [新しいソリューションの作成] に設定します。 オフになっている場合は、[ ソリューションのディレクトリの作成 ] をオンにします。

    Windows コンソール アプリケーションが強調表示され、[名前] テキスト ボックスに Math Client が入力されている [新しいプロジェクト] ダイアログ ボックスのスクリーンショット。

  3. [ OK] を 選択して、クライアント アプリ プロジェクトを作成します。

最小限のコンソール アプリケーション プロジェクトが自動的に作成されます。 メイン ソース ファイルの名前は、前に入力したプロジェクト名と同じです。 この例では、 MathClient.cppという名前です。 ビルドすることはできますが、DLL はまだ使用されていません。

Visual Studio 2015 でクライアント アプリを作成するには

  1. 作成した DLL を使用する C++ アプリを作成するには、メニュー バーの [ ファイル>New>Project] を選択します。

  2. [新しいプロジェクト] ダイアログの左側のウィンドウで、[インストール済み]、[Templates>Visual C++>] の [Win32] を選択します。 中央のウィンドウで、[ Win32 コンソール アプリケーション] を選択します。 [名前] 編集ボックスに、プロジェクトの名前 MathClient 指定します。 既定の [場所 ] と [ソリューション名] の 値のままにします。 [ソリューション] を [新しいソリューションの作成] に設定します。 オフになっている場合は、[ ソリューションのディレクトリの作成 ] をオンにします。

    [新しいプロジェクト] ダイアログ ボックスのスクリーンショット。Win32 コンソール アプリケーション Visual C に加えて強調表示され、[名前] テキスト ボックスに Math Client が入力されています。

  3. [ OK ] ボタンを選択して [新しいプロジェクト ] ダイアログを閉じ、 Win32 アプリケーション ウィザードを起動します。 [Win32 アプリケーション ウィザード] ダイアログ ボックスの [概要] ページで、[次へ] ボタンをクリックします。

  4. [ アプリケーションの設定] ページの [ アプリケーションの種類] で、 コンソール アプリケーション がまだ選択されていない場合は選択します。

  5. [ 完了 ] ボタンを選択してプロジェクトを作成します。

ウィザードが完了すると、最小限のコンソール アプリケーション プロジェクトが自動的に作成されます。 メイン ソース ファイルの名前は、前に入力したプロジェクト名と同じです。 この例では、 MathClient.cppという名前です。 ビルドすることはできますが、DLL はまだ使用されていません。

次に、ソース コードで MathLibrary 関数を呼び出すには、プロジェクトに MathLibrary.h ファイルを含める必要があります。 このヘッダー ファイルをクライアント アプリ プロジェクトにコピーし、既存の項目としてプロジェクトに追加できます。 この方法は、サード パーティ製ライブラリに適しています。 ただし、DLL とクライアントのコードを同時に操作している場合は、ヘッダー ファイルが同期を失う可能性があります。この問題を回避するには、プロジェクトの [追加インクルード ディレクトリ] パスを、元のヘッダーへのパスを含むように設定します。

インクルード パスに DLL ヘッダーを追加するには

  1. ソリューション エクスプローラーMathClient ノードを右クリックし、[プロパティ ページ] ダイアログを開きます。

  2. [ 構成 ] ドロップダウン ボックスで、[ すべての構成] を選択します (まだ選択されていない場合)。

  3. 左側のウィンドウで、 構成プロパティ>C/C++>General を選択します。

  4. プロパティ ウィンドウで、[ 追加のインクルード ディレクトリ ] 編集ボックスの横にあるドロップダウン コントロールを選択し、[編集] を選択 します

    [追加インクルード ディレクトリ] プロパティ ドロップダウンの [編集] コマンドを示す [プロパティ ページ] ダイアログのスクリーンショット。

  5. [ 追加のインクルード ディレクトリ ] ダイアログ ボックスの上部ウィンドウをダブルクリックして、編集コントロールを有効にします。 または、フォルダー アイコンを選択して新しいエントリを作成します。

  6. 編集コントロールで、 MathLibrary.h ヘッダー ファイルの場所へのパスを指定します。 省略記号 (...) コントロールを選択して、正しいフォルダーを参照できます。

    また、クライアント ソース ファイルから DLL ヘッダー ファイルを含むフォルダーへの相対パスを入力することもできます。 DLL とは別のソリューションにクライアント プロジェクトを配置する指示に従った場合、相対パスは次のようになります。

    ..\..\MathLibrary\MathLibrary

    DLL とクライアント プロジェクトが同じソリューション内にある場合、相対パスは次のようになります。

    ..\MathLibrary

    DLL プロジェクトとクライアント プロジェクトが他のフォルダーにある場合は、一致するように相対パスを調整します。 または、省略記号コントロールを使用してフォルダーを参照します。

    MathLibrary ディレクトリへの相対パスを示す [追加のインクルード ディレクトリ] ダイアログのスクリーンショット。

  7. [ 追加のインクルード ディレクトリ ] ダイアログ ボックスでヘッダー ファイルへのパスを入力したら、[ OK ] ボタンを選択します。 [ プロパティ ページ ] ダイアログ ボックスで、[ OK ] ボタンを選択して変更を保存します。

MathLibrary.h ファイルを含め、クライアント アプリケーションで宣言する関数を使用できるようになりました。 次のコードを使用して、 MathClient.cpp の内容を置き換えます。

// MathClient.cpp : Client app for MathLibrary DLL.
// #include "pch.h" Uncomment for Visual Studio 2017 and earlier
#include <iostream>
#include "MathLibrary.h"

int main()
{
    // Initialize a Fibonacci relation sequence.
    fibonacci_init(1, 1);
    // Write out the sequence values until overflow.
    do {
        std::cout << fibonacci_index() << ": "
            << fibonacci_current() << std::endl;
    } while (fibonacci_next());
    // Report count of values written before overflow.
    std::cout << fibonacci_index() + 1 <<
        " Fibonacci sequence values fit in an " <<
        "unsigned 64-bit integer." << std::endl;
}

このコードはコンパイルできますが、リンクすることはできません。 ここでクライアント アプリをビルドすると、エラー一覧にいくつかのLNK2019エラーが表示されます。 これは、プロジェクトに情報が不足しているためです。プロジェクトが MathLibrary.lib ライブラリに依存していることをまだ指定していません。 また、 MathLibrary.lib ファイルを見つける方法をリンカーに伝えていません。

この問題を解決するには、ライブラリ ファイルをクライアント アプリ プロジェクトに直接コピーします。 リンカーはそれを自動的に検索して使用します。 ただし、ライブラリとクライアント アプリの両方が開発中の場合、一方のコピーがもう一方に表示されない変更につながる可能性があります。 この問題を回避するには、 追加の依存関係 プロパティを設定して、プロジェクトが MathLibrary.libに依存していることをビルド システムに伝えることができます。 また、リンク時に元のライブラリへのパスを含める追加のライブラリ ディレクトリ パスをプロジェクトに設定できます。

DLL インポート ライブラリをプロジェクトに追加するには

  1. ソリューション エクスプローラーMathClient ノードを右クリックし、[プロパティ] を選択して [プロパティ ページ] ダイアログを開きます。

  2. [ 構成 ] ドロップダウン ボックスで、[ すべての構成] を選択します (まだ選択されていない場合)。 これにより、プロパティの変更がデバッグ ビルドとリリース ビルドの両方に適用されます。

  3. 左側のウィンドウで、 構成プロパティ>Linker>Input を選択します。 プロパティ ウィンドウで、[ 追加の依存関係 ] 編集ボックスの横にあるドロップダウン コントロールを選択し、[編集] を選択 します

    [追加の依存関係] プロパティ ドロップダウンの [編集] コマンドを示す [入力] の [プロパティ ページ] ダイアログ ボックスのスクリーンショット。

  4. [ 追加の依存関係 ] ダイアログで、上部の編集コントロールの一覧に MathLibrary.lib を追加します。

    MathLibrary.lib ファイルを示す [追加の依存関係] ダイアログ ボックスのスクリーンショット。

  5. [ OK] を 選択して [ プロパティ ページ ] ダイアログ ボックスに戻ります。

  6. 左側のウィンドウで、 構成プロパティ>Linker>General を選択します。 プロパティ ウィンドウで、[ 追加のライブラリ ディレクトリ ] 編集ボックスの横にあるドロップダウン コントロールを選択し、[編集] を選択 します

    [全般] の [プロパティ ページ] ダイアログ ボックスのスクリーンショット。[追加のライブラリ ディレクトリ] プロパティ ドロップダウンに [編集] コマンドが表示されています。

  7. [ 追加のライブラリ ディレクトリ ] ダイアログ ボックスの上部ウィンドウをダブルクリックして、編集コントロールを有効にします。 編集コントロールで、 MathLibrary.lib ファイルの場所へのパスを指定します。 既定では、DLL ソリューション フォルダーのすぐ下にある Debug という名前のフォルダーにあります。 リリース ビルドを作成すると、ファイルは Release という名前のフォルダーに配置されます。 $(IntDir) マクロを使用すると、作成するビルドの種類に関係なく、リンカーが DLL を見つけることができます。 DLL プロジェクトとは別のソリューションにクライアント プロジェクトを配置する指示に従った場合、相対パスは次のようになります。

    ..\..\MathLibrary\$(IntDir)

    DLL プロジェクトとクライアント プロジェクトが他の場所にある場合は、一致するように相対パスを調整します。

    [追加のライブラリ ディレクトリ] ダイアログのスクリーンショット。

  8. [追加のライブラリ ディレクトリ ] ダイアログ ボックスでライブラリ ファイルへのパスを入力したら、[ OK] ボタンを選択して [ プロパティ ページ ] ダイアログ ボックスに戻ります。 [ OK] を 選択してプロパティの変更を保存します。

クライアント アプリは正常にコンパイルしてリンクできるようになりましたが、実行に必要なものがすべて揃っているわけではありません。 オペレーティング システムがアプリを読み込むと、MathLibrary DLL が検索されます。 特定のシステム ディレクトリ、環境パス、またはローカル アプリ ディレクトリに DLL が見つからない場合、読み込みが失敗します。 オペレーティング システムによっては、次のようなエラー メッセージが表示されます。

エラー ダイアログのスクリーンショット。MathLibrary DLL が見つかりません。

この問題を回避する 1 つの方法は、ビルド プロセスの一部としてクライアント実行可能ファイルを含むディレクトリに DLL をコピーすることです。 ビルド後のイベントをプロジェクトに追加して、DLL をビルド出力ディレクトリにコピーするコマンドを追加できます。 ここで指定したコマンドは、DLL が見つからないか変更された場合にのみ、DLL をコピーします。 ビルド構成に基づいて、マクロを使用してデバッグまたはリリースの場所との間でコピーを行います。

ビルド後のイベントで DLL をコピーするには

  1. ソリューション エクスプローラーMathClient ノードを右クリックし、[プロパティ] を選択して [プロパティ ページ] ダイアログを開きます。

  2. [ 構成 ] ドロップダウン ボックスで、[ すべての構成] を選択します (まだ選択されていない場合)。

  3. 左側のウィンドウで、 構成プロパティ>Build イベント>Post-Build イベントを選択します。

  4. プロパティ ウィンドウで、[ コマンド ライン ] フィールドで編集コントロールを選択します。 指示に従って、クライアント プロジェクトを DLL プロジェクトとは別のソリューションに配置した場合は、次のコマンドを入力します。

    xcopy /y /d "..\..\MathLibrary\$(IntDir)MathLibrary.dll" "$(OutDir)"

    DLL プロジェクトとクライアント プロジェクトが他のディレクトリにある場合は、DLL への相対パスを一致するように変更します。

    ビルド後イベントのコマンド ライン プロパティを示す [プロパティ ページ] ダイアログのスクリーンショット。

  5. [ OK] ボタンを選択して、プロジェクトのプロパティに対する変更を保存します。

これで、クライアント アプリにビルドと実行に必要なものがすべて揃いました。 メニュー バーの [ Build>Build Solution ] を選択して、アプリケーションをビルドします。 Visual Studio の [出力] ウィンドウには、Visual Studio のバージョンに応じて次の例のようなものが表示されます。

1>------ Build started: Project: MathClient, Configuration: Debug Win32 ------
1>MathClient.cpp
1>MathClient.vcxproj -> C:\Users\username\Source\Repos\MathClient\Debug\MathClient.exe
1>1 File(s) copied
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

これで、DLL で関数を呼び出すアプリケーションが作成されました。 次に、アプリケーションを実行して、実行内容を確認します。 メニュー バーで、[デバッグ] > [デバッグなしで開始] を選択します。 Visual Studio によって、プログラムを実行するためのコマンド ウィンドウが開きます。 出力の最後の部分は次のようになります。

デバッグなしでクライアント アプリを起動したときのコマンド ウィンドウの出力のスクリーンショット。

任意のキーを押してコマンド ウィンドウを閉じます。

DLL とクライアント アプリケーションを作成したので、実験を行うことができます。 クライアント アプリのコードにブレークポイントを設定して、デバッガーでアプリを実行してみてください。 ライブラリ呼び出しにステップ インするとどうなるかを確認します。 ライブラリに他の関数を追加するか、DLL を使用する別のクライアント アプリを記述します。

アプリをデプロイするときは、使用する DLL もデプロイする必要があります。 ビルドする DLL、またはサード パーティから含める DLL を使用できるようにする最も簡単な方法は、それらをアプリと同じディレクトリに配置することです。 これはアプリ ローカルデプロイと呼ばれます。 展開の詳細については、「 Microsoft C++ での展開」を参照してください。

こちらも参照ください