LoginSignup
0
0

[初級] C++: プログラムのビルド(ライブラリの利用)

Last updated at Posted at 2024-05-25

C++ のプログラムでライブラリを利用する場合の超基本的なこと
スタティックライブラリ, ダイナミックリンクライブラリ
Visual Studio, VC++, Windows

本記事の前提条件は以下の通りです。

  • 初心者向け
  • とは言っても、何らかのプログラムはそれなりに書けるけど、C とか C++ はちょっと、という人向け
  • ざっくり概要しか説明しないので細かいことは気にしないでいただきたい
  • Visual Studio 2013 くらい~
  • Windowsプログラム (CUI, GUI)
  • コードの検証
    • 開発環境: Visual Studio 2022, x64, Release ビルド
    • 実行環境: Windows 10
  • 本記事は上から順番に読む前提となっている
  • 「C++」と書いてあるが、本記事の内容としては C でもほぼ同じ
  • 「Visual Studio 2013 くらい~」と書いてあるが、本記事の内容だと現在過去未来のどのバージョンでもほぼ同じ
  • 「Windowsプログラム (CUI, GUI)」と書いてあるが、本記事の内容だとどの OS でもほぼ同じ。ただし、ダイナミックリンクライブラリ(共有ライブラリ)の作り方、使い方については OS によって違いがあるので注意
  • その他、エラーコードなどについても状況によって異なるので注意
  • 「...ライブラリ」「...リンクライブラリ」どちらでもよいと思うが、マイクロソフト的には「スタティックライブラリ」「ダイナミックリンクライブラリ」としているようなのでそれに従っている
  • DLL を使う場合、(Visual Studio のテンプレートを使ったとしても)実際にはいろいろと処理が必要なのだが、本記事ではそのあたりの詳細には触れないのであしからず

前提知識として必要と思われる情報

そもそもライブラリとは

「図書館」ではさすがにわかりにくいので、「収集コレクション」と考えるのがよいと思う。

コンピュータープログラムにおいては、同じ処理を使いまわすための仕組みということで、単なるコードスニペット群もライブラリと呼べるかと思うが、ここでは、C++ における *.lib ファイル、および、*.dll を対象とする。

静的と動的

ライブラリには、スタティックライブラリ、ダイナミックリックライブラリがある。

以下に、その作り方、使い方を記述し、違いを見てみる。

ライブラリにしたい処理を作る

例えばここに、共通に利用したい関数 int add(int a, int b) があるとする。

c++ calc.h
int add(int a, int b);
c++ calc.cpp
int add(int a, int b)
{
    return a + b;
}

ソースコードを書き、とりあえずコンパイルし、calc.obj を作成しておく。

スタティックライブラリ

スタティックライブラリを作る

ライブラリアン lib.exe でスタティックライブラリを作成する。

lib.exe calc.obj /out:calc.lib

ライブラリアンは *.lib の管理をするツールで、後で別の *.obj を追加したりできる。
つまり、*.lib*.obj の収集コレクション = ライブラリ、ということである。

スタティックライブラリを使う

ヘッダファイルをインクルードしてコンパイルする。

c++ main.cpp
#include <iostream>
#include "calc.h"
int main()
{
    std::cout << add(1, 2) << std::endl;
    return 0;
}

cl.exe main.cpp

これで main.obj が生成される。

リンカに、main.obj と、calc.lib を渡してリンクする。

link.exe main.obj calc.lib /out:hogehoge.exe

ライブラリを使わない場合と比べると、リンカに渡すものが calc.obj から calc.lib になっただけである。

上記ソースコードを実際にリンクする場合には、VCランタイムなどが追加で必要なのであしからず。

スタティックライブラリを使った場合のポイント

スタティックライブラリを使った場合のポイントとしては、生成された hogehoge.exe の中に add 関数の本体が埋め込まれている、ということである。

ダイナミックリンクライブラリ

ダイナミックリンクライブラリを作る

リンカで calc.obj をダイナミックリンクライブラリとしてリンクするのだが、DLL を作成する場合には、どの関数をエクスポートするか、を指定する必要がある。
いくつかの方法があるのだが、それについては本記事では説明しないのであしからず。

参考: DLL と実行形式のリンク - Microsoft Learn

なんにせよ、calc.obj を含んだ calc.dll ができたとする。

ダイナミックリンクライブラリを使う(Explicit Linking)

ダイナミックリンクライブラリを使う場合には、実行時に DLL から必要な関数を読み込む必要があり、下記のようになる。

c++ main.cpp
#include <windows.h>
#include <tchar.h>
#include <iostream>
int main()
{
    // DLL をロードする
    HMODULE hLib = LoadLibrary(_T("calc.dll"));
    typedef int (*PFUNC_ADD)(int, int);
    // add 関数のアドレスを取得する
    PFUNC_ADD add = (PFUNC_ADD)GetProcAddress(hLib, "add");

    // 使う
    std::cout << add(1, 2) << std::endl;

    // DLL を解放する
    FreeLibrary(hLib);
    return 0;
}

とにかく DLL から関数を読み込む必要がある、ということがわかればよいので、上記コードの詳細は割愛する。

ダイナミックリンクライブラリを使う(Implicit Linking)

DLL を作成する場合、(設定によるが、通常)リンカはインポートライブラリ calc.lib を出力する。
このインポートライブラリには、add 関数の実体は含まれておらず、その代わりに calc.dlladd 関数を「実行時(exe の起動時)にロードする」処理が含まれている。

したがって、ダイナミックリンクライブラリを使う場合でも、ソースコード上はスタティックライブラリを使う時と同じで、まずはヘッダをインクルードしてコンパイルする。

c++ main.cpp
#include <iostream>
#include "calc.h"
int main()
{
    std::cout << add(1, 2) << std::endl;
    return 0;
}

スタティックライブラリを使う場合との違いは、リンカに渡す calc.lib がインポートライブラリである、という点のみである。

インポートライブラリをリンクした exe は、起動時に必要な DLL から必要な関数をロードして利用する。

ダイナミックリンクライブラリを使う場合のポイント

ダイナミックリンクライブラリを使う場合のポイントとしては、生成された hogehoge.exe の中には add 関数の本体はなく、実行時に見つかった DLL のものを利用する、ということである。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0