記事内にはプロモーションが含まれています

【C++】DLL呼び出しの完全ガイド!静的リンク・動的リンクの実装からC#連携まで

【C++】DLL呼び出しの完全ガイド!静的リンク・動的リンクの実装からC#連携まで C++

Windowsアプリケーション開発において、機能のモジュール化や再利用性を高めるために欠かせないのが「DLL(Dynamic Link Library)」です。

しかし、いざC++でDLLを作成・呼び出ししようとすると、「ライブラリ(.lib)が見つからない」「関数がエクスポートされていない」といったリンクエラーに悩まされることがよくあります。

また、DLLの呼び出し方には「静的リンク(暗黙的リンク)」と「動的リンク(明示的リンク)」の2種類があり、さらに「C#からC++のDLLを使いたい」というケースも多いため、状況に応じた正しい実装方法を知っておく必要があります。

この記事では、Visual Studio 2022(または最新環境)を使用したC++でのDLL作成と呼び出しの基本から、LoadLibrary を使った動的ロード、そしてC#との連携方法まで、実務で役立つ知識をサンプルコード付きで徹底解説します。

【本記事の信頼性】
プロフィール
執筆者:マヒロ
  • 執筆者は元エンジニア
  • SES⇒大手の社内SE⇒独立
  • 現在はプログラミングスクールを運営
  • モットーは「利他の精神」
💻 本記事の検証環境(2026年2月確認)
  • OS:Windows 11 / macOS Sequoia
  • IDE:Visual Studio / VS Code / IntelliJ IDEA
  • その他:Chrome DevTools / 各言語最新安定版

※本メディアでは、上記環境にてコードの動作と情報の正確性を検証済みです。

DLL呼び出しの2つの方式:静的リンクと動的リンク

C++からDLLを利用する方法は、大きく分けて以下の2通りがあります。
それぞれの特徴を理解して使い分けましょう。

1. 静的リンク(暗黙的リンク / Implicit Linking)

  • 仕組み: コンパイル時に .lib(インポートライブラリ)をリンクし、アプリ起動時に自動的にDLLを読み込む。
  • メリット: 関数を通常の関数と同じように呼び出せるため、コードがシンプルになる。
  • デメリット: 実行時にDLLが存在しないとアプリが起動しない。

2. 動的リンク(明示的リンク / Explicit Linking)

  • 仕組み: 実行中に LoadLibrary 関数を使ってDLLを読み込み、GetProcAddress で関数ポインタを取得して実行する。
  • メリット: 必要な時だけDLLを読み込める(メモリ節約)。DLLが無くてもアプリ自体は起動できる(エラー処理が可能)。
  • デメリット: 関数ポインタの定義や呼び出しのコードが複雑になる。プラグインシステムなどでよく使われる。

【実践】C++でDLLを作成し、静的リンクで呼び出す

まずは最も一般的な「静的リンク」の手順を見ていきましょう。
DLL側で関数を公開(エクスポート)し、アプリ側でそれを呼び出します。

ステップ1:DLLの作成(エクスポート)

DLLを作成するプロジェクト(例:MyMathDll)を作成し、ヘッダーファイルとソースファイルを用意します。

重要なのは __declspec(dllexport) というキーワードです。

MyMathDll.h

#pragma once

#ifdef MYMATHDLL_EXPORTS
#define MYMATH_API __declspec(dllexport)
#else
#define MYMATH_API __declspec(dllimport)
#endif

// 外部に公開する関数
extern "C" MYMATH_API int Add(int a, int b);

MyMathDll.cpp

#include "pch.h" // Visual Studioの場合
#include "MyMathDll.h"

// 関数の実装
int Add(int a, int b) {
    return a + b;
}

extern "C" を付けることで、C++特有の「名前修飾(Name Mangling)」を防ぎ、他の言語やコンパイラからも呼び出しやすくしています。

__declspec(dllexport) は「この関数をDLLの外に見せる」という意味です。

呼び出し側(インポート側)では __declspec(dllimport) に切り替わるようにマクロ(MYMATH_API)を定義するのが定石です。

ステップ2:アプリ側からの呼び出し(インポート)

次に、作成したDLLを利用するアプリ側(例:MyApp)の実装です。
ビルドするには、DLLのヘッダーファイル(.h)とインポートライブラリ(.lib)が必要です。

main.cpp

#include <iostream>
#include "MyMathDll.h" // DLLのヘッダーをインクルード

// ライブラリのリンク(プロパティ設定でも可)
#pragma comment(lib, "MyMathDll.lib")

int main() {
    int result = Add(10, 20);
    std::cout << "計算結果: " << result << std::endl;
    return 0;
}

実行結果

計算結果: 30

実行時には、作成された MyMathDll.dll を実行ファイル(.exe)と同じフォルダに置く必要があります。

【応用】LoadLibraryを使った動的リンク(明示的リンク)

プラグイン機能のように、「実行中にDLLを切り替えたい」「DLLがあるかどうかわからない」といった場合は、Windows APIを使った動的リンクを行います。

.lib ファイルやヘッダーファイルがなくても、DLLさえあれば関数を呼び出せるのが特徴です。

動的リンクの実装コード

#include <iostream>
#include <windows.h> // LoadLibrary, GetProcAddressに必要

// 関数ポインタの型定義
typedef int (*AddFunc)(int, int);

int main() {
    // 1. DLLのロード
    HMODULE hDll = LoadLibrary(L"MyMathDll.dll");
    if (hDll == NULL) {
        std::cerr << "DLLが見つかりません。" << std::endl;
        return 1;
    }

    // 2. 関数のアドレスを取得
    AddFunc add = (AddFunc)GetProcAddress(hDll, "Add");
    if (add == NULL) {
        std::cerr << "関数が見つかりません。" << std::endl;
        FreeLibrary(hDll);
        return 1;
    }

    // 3. 関数の実行
    int result = add(50, 50);
    std::cout << "動的リンクでの計算結果: " << result << std::endl;

    // 4. DLLの解放
    FreeLibrary(hDll);
    
    return 0;
}

LoadLibrary でDLLをメモリに読み込み、GetProcAddress で関数名(文字列)からその関数のメモリ上のアドレスを探し出します。

見つかったアドレスを関数ポインタ(AddFunc)にキャストすることで、関数として実行できるようになります。

使い終わったら必ず FreeLibrary で解放しましょう。

【C#連携】C#からC++のDLLを呼び出す方法(P/Invoke)

業務アプリ開発では、パフォーマンスが必要な部分だけC++でDLLを作り、UI部分はC#(WPFやWinForms)で作るという構成がよくあります。

C#からアンマネージド(Native)なC++ DLLを呼ぶには、「プラットフォーム呼び出し(P/Invoke)」を使用します。

C#側の実装コード

C++側は先ほどの MyMathDll.dllextern "C" 付き)をそのまま使用します。

using System;
using System.Runtime.InteropServices; // DllImportに必要

class Program
{
    // DLLの関数を定義
    // CallingConventionはC++側の仕様に合わせる(通常はCdeclかStdCall)
    [DllImport("MyMathDll.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int Add(int a, int b);

    static void Main()
    {
        try
        {
            int result = Add(100, 200);
            Console.WriteLine($"C#からの呼び出し結果: {result}");
        }
        catch (DllNotFoundException)
        {
            Console.WriteLine("DLLファイルが見つかりません。");
        }
    }
}

実行結果

C#からの呼び出し結果: 300

[DllImport("DLL名")] 属性を付けた static extern メソッドを定義するだけで、C++の関数をC#メソッドのように扱えます。

注意点として、C++とC#では型のサイズやメモリ管理が異なるため、文字列(char*string)や配列を渡す場合は「マーシャリング(Marshaling)」というデータ変換の知識が必要になります。

基本型(intやdouble)であればそのまま渡せます。

C++のスキルを活かして年収を上げる方法

以上、C++でのDLL呼び出し方法について解説しました。

なお、C++のスキルがある場合には、「転職して年収をアップさせる」「副業で稼ぐ」といった方法を検討するのがおすすめです。

C++を扱えるエンジニアは希少価値が高いため、転職によって数十万円の年収アップはザラで、100万円以上年収が上がることも珍しくありません。

なお、転職によって年収を上げたい場合は、エンジニア専門の転職エージェントサービスを利用するのが最適です。
今すぐ転職する気がなくとも、とりあえず転職エージェントに無料登録しておくだけで、スカウトが届いたり、思わぬ好待遇の求人情報が送られてきたりするというメリットがあります。
併せて、副業案件を獲得できるエージェントにも登録しておくと、空いている時間を活かして稼げるようなC++の案件を探しやすくなります。

転職エージェントも副業エージェントも、登録・利用は完全無料なので、どんな求人や副業案件があるのか気になる方は、気軽に利用してみるとよいでしょう。
エンジニアのキャリア・スキルアップ相談窓口
当ブログの読者に選ばれている、実績豊富な転職エージェントを厳選しました。
【転職】年収・環境を改善したい
年収アップにこだわりたい方 (平均アップ額138万円の実績)
未経験・経験者問わず幅広く探したい方
業界に精通した担当者に相談したい方
ゲーム業界への転職を志望する方
エンジニア未経験からキャリアを築く方
【独立】フリーランスとして稼ぎたい
国内最大級のフリーランス案件数から比較したい方
週1〜3日など柔軟な働き方を希望する方
【学習】スキルに不安のある方向け(格安スクール「デイトラ」)