パソコンでプログラミングしよう ウィンドウズC++プログラミング環境の構築
1.6.3.6(15)
ライブラリ

ライブラリは汎用性の高い複数のプログラムを再利用可能な形でひとまとまりにしたものである。

その他の外部情報

本サイトでの解釈

C++標準ライブラリはmingw-w64の一部として導入される。MSYS2はその際にiconvなどのライブラリを導入する。本サイトではさらにboostライブラリとwxWidgetsライブラリを追加導入する。

ライブラリの実装方法

mingw-w64でウィンドウズアプリケーションを開発する場合のライブラリ実装方法を分類する。

ライブラリ .hファイル .aファイル .dllファイル
スタティックリンク
ダイナミックリンク ロード時動的リンク
実行時動的リンク
ヘッダオンリー

ライブラリを構成するファイルは以下になる。

覚え書き
以下のオプション記述に大文字のアイ(-I)と小文字のエル(-l)が混在し見分けがつかなくなっている可能性があるため、事前に定義しておく。本文中は申し訳ないが文脈から判断いただききたい。
  • 大文字のアイ(-I)、インクルードディレクトリの指定
  • 小文字のエル(-l)、ライブラリファイルの指定
拡張子 ファイル 使用 探索パス
.h インクルード コンパイル時 -Iオプションなど、コンパイラ標準インクルードディレクトリ
.a (スタティックリンク)ライブラリ リンク時 -Lオプション、コンパイラ標準ライブラリディレクトリ
.dll ダイナミックリンクライブラリ 実行時 実行ファイルディレクトリなど、環境変数PATH

ダイナミックリンクライブラリ(DLL)実行時動的リンクは他と用法が異なるとして議論から排除すれば、インクルードファイルはライブラリインターフェースを公開し必須である。スタティックリンクライブラリはコンパイル済みライブラリ関数をライブラリファイルで供給し、クライアントはこれを静的リンクする。DLLロード時動的リンクはクライアントとDLLファイルを仲介するライブラリ(DLLインポートライブラリ)ファイルを供給し、クライアントはこれを静的リンクする。例えばスタティックリンクライブラリlibfile1.aに対し、DLLインポートライブラリは多くの場合libfile1.dll.aで区別される。ヘッダオンリーライブラリは全てのライブラリ関数をインライン形式で与えライブラリファイルは無く、テンプレートライブラリのほとんどがこれに相当する。MSYS2導入ライブラリは例外を除き標準ディレクトリに配置され-Iオプションや-Lオプションは不要である。ディレクトリ探索順はインクルードで特に複雑で、厳密にはGNUcppドキュメントを参照する。標準インクルードディレクトリと標準ライブラリディレクトリはmingw32ターミナルあるいはmingw64ターミナルから確認できる。

$ cpp -v /dev/null -o /dev/null
$ ld --verbose | grep SEARCH_DIR

インクルードファイルは#includeディレクティブでソースコードにインクルードする。良く設計されたライブラリならインクルード順は不問だがそうでない例も多く、例えばfile1.hがfile2.hの関数を用いながら自らはfile2.hをインクルードしない場合はfile2.h、file1.hの順番にインクルードする。ライブラリファイルはコンパイラオプション-lで指定するが、例えばlibfile1.aというライブラリファイルはfile1あるいはlibfile1.aとして指定する。libfile1.aがlibfile2.aの未参照関数を用いる場合、インクルードと逆にlibfile1.a、libfile2.aの順番に指定する。

統合開発環境Code::Blocksにおいてインクルードディレクトリ(-I)、ライブラリディレクトリ(-L)、ライブラリファイル(-l)はビルドオプション設定の一部として与える。一方環境変数PATHはアプリケーション実行時の問題でビルドオプションに関係しない。

C++標準ライブラリ

C++標準ライブラリと以下の用語について整理する。

  • C言語標準ライブラリ
  • ランタイムライブラリ
  • 標準テンプレートライブラリ

C++がC言語の上位互換であるのに対応し、C++標準ライブラリはC言語標準ライブラリを内包する。

C++/C言語標準ライブラリとランタイムライブラリは概念的に別物とされるが、本サイトを含め多くの場合に混同する。マイクロソフトはVisual C++(マイクロソフトのC++コンパイラ)標準ライブラリを実装するDLLをランタイムDLLと呼ぶが、さらに同じ機能を静的リンクで実現するライブラリファイルもランタイムと呼ぶ。定義上の問題を意識しながらも、本サイトはランタイムライブラリをC++標準ライブラリをMSYS2において実装するライブラリファイルとして参照する。「C++標準ライブラリはランタイムライブラリと標準テンプレートライブラリから成立する」は明らかに誤った言明だが、実用上は的を得ている。mingw-w64はデフォルトでランタイムライブラリをリンクするが、-staticオプションの有無でそのスタティックリンクライブラリとダイナミックリンクライブラリを選択する。

標準テンプレートライブラリ(Standard Template Library, STL)は元々はヒューレット・パッカードの開発したライブラリの名称であり、そのC++標準ライブラリに取り込まれた部分を現在はSTLと通称する。任意タイプの集合(コンテナ)とその要素を順次処理する自由関数(アルゴリズム)で構成され、コンテナはクラステンプレート、アルゴリズムは要素を指すオブジェクト(イテレータ)をテンプレート仮引数とする関数テンプレートである。異なった特性を持つコンテナを静的多態性で抽象化し、総称プログラミングの最大の成果と見なされる。そのほとんどがヘッダオンリーライブラリで供給される。サイト作成者は当初イテレータの存在理由を理解しなかったが、それがコンテナとアルゴリズムを分離抽象化することを学び(Nicolai M. Josuttis, The C++ Standard Library, Boston, Addison-Wesley, 1999; Boston, Addison-Wesley, 2004, pp.73-75)直感的にSTLを使えるようになった。未だ使うたびに惑う入出力ライブラリiostreamとは大きな違いだ。

boostライブラリ

boostライブラリはC++標準ライブラリの先駆となる実験的ライブラリで、それぞれが独立したライブラリの集合体である。多くはヘッダオンリーライブラリだがスタティック/ダイナミックリンクライブラリとして供給されるものもある。C++11でC++標準ライブラリに追加されたbind、enable_if、function、regex、shared_ptrなどはboostをベースとしている。実用性はともかく先進的な機能は刺激的で、例えばmplライブラリは型リスト(Andrei Alexandrescu, Modern C++ Design, Boston, Addison-Wesley, 2001: Boston, Addison-Wesley, 2002, pp.49-76)をSTLに似して実装するが、これをメタプログラミングの精華と呼ぶのは大袈裟だろうか。

boostは無名関数さえもライブラリで実現した。無名関数はC++11で構文化されライブラリは不要となったが、今なおC++のソースコード記述能力を示す好例と考える。以下のサンプルソースコードはlambdaライブラリによる完全に正当なC++ソースコードである。

#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/control_structures.hpp>
int main()
{
using namespace boost::lambda;
auto values=std::vector<unsigned int>{0,1,2,3,4,5};
auto i=(unsigned int){};
auto factorial=(unsigned int){};
std::for_each(values.begin(),values.end(),
(
if_ (_1%2)
[
std::cout<<_1<<" is odd.\n"
].
else_
[
std::cout<<_1<<" is even.\n"
],
var(factorial)=1,
for_ (var(i)=1,var(i)<=_1,++var(i))
[
var(factorial)*=var(i)
],
std::cout<<constant("Factorial of ")<<_1<<" is "<<var(factorial)<<".\n",
std::cout<<constant("----------------------------------------------\n")
));
return 0;
}

本サイトはMSYS2でビルド済み導入するがソースコードから自らビルドする事もできる。

wxWidgetsライブラリ

wxWidgetsはウィンドウズとユニックスライクを含むマルチプラットフォーム対応のC++ライブラリでGUIフレームワークを提供する。エミュレータを用いずネイティブAPIを直接コールし、ターゲットプラットフォームに完全に沿うルックアンドフィールを得る。

本サイトはウィンドウズデスクトップアプリケーションの開発にwxWidgetsを使用するがマルチプラットフォーム対応はあまり考慮しない。ウィンドウズアプリケーションはウィンドウズAPIのみで開発できるが非常に面倒で、ラッパーライブラリの利用は必然とされる。商業コンパイラではマイクロソフトVisual C++にはMicrosoft Foundation Class(MFC)が、エンバカデロC++ BuilderにはVisual Component Library(VCL)が添付される。フリーなライブラリはQtかwxWidgetsのどちらかの選択で本サイトは特に理由も無くwxWidgetsを選択する。

MSYS2の導入するwxWidgetsライブラリはインクルードファイルをmingw-w64標準より1階層下のディレクトリ(例えばC:\msys64\mingw32\include\wx-3.0)にインストールする。またコンパイラやライブラリビルド時のコンフィグに依存するwx/setup.hファイルを標準ライブラリディレクトリの階層下(例えばC:\msys64\mingw32\lib\wx\include\msw-unicode-static-3.0)にインストールする。本サイト作成のwxWigetsプロジェクトウィザードはこれらをインクルードディレクトリに追加する。

wxWidgetsは複数の分割されたライブラリファイル(非モノリシック)または単一の大きなライブラリファイル(モノリシック)で供給される。MSYS2の導入するwxWidgetsは非モノリシックで各ライブラリファイルのリンク順に悩む可能性がある。モノリシック/非モノリシックにかかわらずwxWidgetsはウィンドウズAPIおよび他のいくつかのライブラリに依存する。本サイト作成のwxWidgetsプロジェクトウィザードは必要最低限と思われるライブラリファイルを追加する。

本サイトはMSYS2でビルド済み導入するがソースコードから自らビルドする事もできる。