Sun Studio 12: C++ ユーザーズガイド

第 12 章 ライブラリの使用

ライブラリを使用すると、アプリケーション間でコードを共有したり、非常に大規模なアプリケーションを単純化できます。C++ コンパイラでは、さまざまなライブラリを使用できます。この章では、これらのライブラリの使用方法を説明します。

12.1 C ライブラリ

Solaris オペレーティングシステムでは、いくつかのライブラリが /usr/lib にイン ストールされます。 このライブラリのほとんどは C インタフェースを持っています。デフォルトでは libc および libm ライブラリが CC ドライバによってリンクされます。 ライブラリ libthread は、-mt オプションを指定した場合にのみリンクされます。 それ以外のシステムライブラリをリンクするには、-l オプションでリンク時に指定する必要があります。 たとえば、libdemangle ライブラリをリンクするには、リンク時に -ldemangleCC コマンド行に指定します。


example% CC text.c -ldemangle

C++ コンパイラには、独自の実行時ライブラリが複数あります。すべての C++ アプリケーションは、CC ドライバによってこれらのライブラリとリンクされます。C++ コンパイラには、次の節に示すようにこれ以外にも便利なライブラリがいくつかあります。

12.2 C++ コンパイラ付属のライブラリ

Sun C++ コンパイラには、いくつかのライブラリが添付されています。 これらのライブラリには、互換モード (-compat=4) だけで使用できるもの、標準モード (-compat=5) だけで使用できるもの、あるいは両方のモードで使用できるものがあります。 libgc ライブラリと libdemangle ライブラリには C インタフェースがあり、どちらのモードでもアプリケーションにリンクできます。

次の表に、Sun C++ コンパイラに添付されるライブラリと、それらを使用できるモードを示します。

表 12–1 C++ コンパイラに添付されるライブラリ

ライブラリ 

内容の説明 

使用できるモード 

libstlport

標準ライブラリの STLport 実装 

-compat=5

libstlport_dbg

デバッグモード用 STLport ライブラリ 

-compat=5

libCrun

C++ 実行時 

-compat=5

libCstd

C++ 標準ライブラリ 

-compat=5

libiostream

従来の iostream

-compat=5

libC

C++ 実行時、従来の iostream

-compat=4

libcsunimath

-xia オプションをサポート

-compat=5

libcomplex

complex ライブラリ

-compat=4

librwtool

Tools.h++ 7

-compat=4, -compat=5

librwtool_dbg

デバッグ可能な Tools.h++ 7

-compat=4,-compat=5

libgc

ガベージコレクション 

C インタフェース 

libdemangle

復号化 

C インタフェース 


注 –

STLport、Rogue Wave、または Sun Microsystems C++ ライブラリの構成マクロを再定義したり変更したりしないでください。 ライブラリは C++ コンパイラとともに動作するよう構成および構築されています。libCstd と Tool.h++ は互いに働き合うように構成されているので、その構成マクロを変更すると、プログラムのコンパイルやリンクが行われなくなったり、プログラムが正しく実行されなくなったりします。


12.2.1 C++ ライブラリの説明

これらのライブラリについて簡単に説明します。


file:/opt/SUNWspro/docs/index.html

コンパイラソフトウェアが /opt ディレクトリにインストールされていない場合は、システム上でこのディレクトリに相当するパスをシステム管理者に問い合わせてください。

12.2.2 C++ ライブラリのマニュアルページへのアクセス

この節で説明しているライブラリに関するマニュアルページは次の場所にあります。

これらのマニュアルページにアクセスするには、MANPATH/opt/SUNWspro/man (またはシステム上でこのディレクトリに相当するパス) が含まれていることを確認してください。

C++ ライブラリのマニュアルページにアクセスするには次のとおり入力してください。


example% man library-name

C++ ライブラリの version 4.2 のマニュアルページにアクセスするには次のコマンドを入力してください。


example% man -s 3CC4 library-name

次のアドレスに Web ブラウザでアクセスしてマニュアルページにアクセスすることもできます。


file:/opt/SUNWspro/docs/index.html

12.2.3 デフォルトの C++ ライブラリ

これらのライブラリには、CC ドライバによってデフォルトでリンクされるものと、明示的にリンクしなければならないものがあります。標準モードでは、次のライブラリが CC ドライバによってデフォルトでリンクされます。

-lCstd -lCrun -lm -lc

互換モード (-compat) では、次のライブラリがデフォルトでリンクされます。

-lC -lm -lc

詳細は、「A.2.49 -library=l[ ,l...]」を参照してください。

12.3 関連するライブラリオプション

CC ドライバには、ライブラリを使用するためのオプションがいくつかあります。


example% CC test.cc -library=rwtools7,iostream

example% CC test.cc -library=gc -staticlib=gc

example% CC test.cc -compat=4 -staticlib=libC

example% CC test.cc -library=no%Crun,no%Cstd

デフォルトでは、CC は、指定されたコマンド行オプションに従ってさまざなシステムライブラリをリンクします。-xnolib (または -nolib) を指定した場合、CC は、-l オプションを使用してコマンド行で明示的に指定したライブラリだけをリンクします。 -xnolib または -nolib を使用した場合、-library オプションが存在していても無視されます。

-R オプションは、動的ライブラリの検索パスを実行可能ファイルに組み込むときに使用します。 実行時リンカーは、実行時にこれらのパスを使ってアプリケーションに必要な共有ライブラリを探します。CC ドライバは、デフォルトで -R/opt/SUNWspro/libld に渡します (コンパイラが標準の場所にインストールされている場合)。共有ライブラリのデフォルトパスが実行可能ファイルに組み込まれないようにするには、-norunpath を使用します。

12.4 クラスライブラリの使用

一般に、クラスライブラリを使用するには 2 つの手順が必要です。

  1. ソースコードに適切なヘッダーをインクルードする。

  2. プログラムをオブジェクトライブラリとリンクする。

12.4.1 iostream ライブラリ

C++ コンパイラには、2 通りの iostream が実装されています。

すでに C++ のソースがある場合、そのコードは従来の iostream を使用しており、次の例のような形式になっていると思われます。


// ファイル prog1.cc
#include <iostream.h>

int main() {
    cout << "Hello, world!" << endl;
    return 0;
}

次のコマンドは、互換性モードで prog1.cc をコンパイル、リンクして、prog1 という実行可能なプログラムを生成します。従来の iostream ライブラリは、互換性モードのときにデフォルトでリンクされる libC ライブラリに含まれています。


example% CC -compat prog1.cc -o prog1

次の例では、標準 iostream が使用されています。


// ファイル prog2.cc
#include <iostream>

int main() {
    std::cout << "Hello, world!" << std::endl;
    return 0;
}

次のコマンドは、prog2.cc をコンパイル、リンクして、prog2 という実行可能なプログラムを生成します。コンパイルは標準モードで行われ、このモードでは、標準の iostream ライブラリを含む libCstd がデフォルトでリンクされます。


example% CC prog2.cc -o prog2

libCstd についての詳細は、「警告:」を参照してください。libiostream の詳細は、「13.3.1 再配布とサポートされる STLport ライブラリ」を参照してください。

コンパイルモードの詳しい説明については、『C++ 移行ガイド』を参照してください。

12.4.2 complex ライブラリ

標準ライブラリには、C++ 4.2 コンパイラに付属していた complex ライブラリに似た、テンプレート化された complex ライブラリがあります。標準モードでコンパイルする場合は、<complex> ではなく、<complex.h> を使用する必要があります。互換性モードで <complex> を使用することはできません。

互換性モードでは、リンク時に complex ライブラリを明示的に指定しなければなりません。標準モードでは、complex ライブラリは libCstd に含まれており、デフォルトでリンクされます。

標準モード用の complex.h ヘッダーはありません。C++ 4.2 では、「complex」 はクラス名ですが、標準 C++ では「complex」はテンプレート名です。したがって、旧式のコードを変更せずに動作できるようにする typedef を使用することはできません。このため、複素数を使用する、4.2 用のコードで標準ライブラリを使用するには、多少の編集が必要になります。たとえば、次のコードは 4.2 用に作成されたものであり、互換性モードでコンパイルされます。


// ファイル ex1.cc (互換モード)
#include <iostream.h>
#include <complex.h>

int main()
{
    complex x(3,3), y(4,4);
    complex z = x * y;
    cout << "x=" << x << ", y=" << y << ", z=" << z << endl;
}

次の例では、ex1.cc を互換モードでコンパイル、リンクし、生成されたプログラムを実行しています。


example% CC -compat ex1.cc -library=complex
example% a.out
x=(3, 3), y=(4, 4), z=(0, 24)

次は、標準モードでコンパイルされるように ex2.cc と書き直された ex1.cc です。


// ファイル ex2.cc (ex1.cc を標準モード用に書き直し)
#include <iostream>
#include <complex>
using std::complex;

int main()
{
     complex<double> x(3,3), y(4,4);
     complex<double> z = x * y;
     std::cout << "x=" << x << ", y=" << y << ", z=" << z <<
       std::endl;
}

次の例では、書き直された ex2.cc をコンパイル、リンクして、生成されたプログラムを実行しています。


% CC ex2.cc
% a.out
x=(3,3), y=(4,4), z=(0,24)

複素数演算ライブラリの使用方法についての詳細は、表 14–4を参照してください。

12.4.3 C++ ライブラリのリンク

次の表は、C++ ライブラリにリンクするためのコンパイラオプションをまとめています。詳細は、「A.2.49 -library=l[ ,l...]」を参照してください。

表 12–2 C++ ライブラリにリンクするためのコンパイラオプション

ライブラリ 

コンパイルモード 

オプション 

従来の iostream

-compat=4

-compat=5

不要 

-library=iostream

complex

-compat=4

-compat=5

-library=complex

不要 

Tools.h++ version 7

-compat=4

-compat=5

-library=rwtools7

-library=rwtools7,iostream

-library=rwtools7_std

デバッグ対応 Tools.h++ version 7

-compat=4

-compat=5

-library=rwtools7_dbg

-library=rwtools7_dbg,iostream

-library=rwtools7_std_dbg

ガベージコレクション

-compat=4

-compat=5

-library=gc

-library=gc

STLport version 4 

-compat=5

-library=stlport4

STLport version 4 デバッグ 

-compat=5

-library=stlport4_dbg

12.5 標準ライブラリの静的リンク

デフォルト時、CC ドライバは、デフォルトライブラリの -llib オプションをリンカーに渡すことによって、libclibm を含むいくつかのライブラリの共有バージョンでリンクします。互換性モードと標準モードにおけるデフォルトライブラリのリストについては、「12.2.3 デフォルトの C++ ライブラリ」を参照してください。

このようにデフォルトのライブラリを静的にリンクする場合、-library オプションと -staticlib オプションを一緒に使用すれば、C++ ライブラリを静的にリンクできます。 この方法は、以前説明した方法よりもかなり簡単です。次に例を示します。


example% CC test.c -staticlib=Crun

この例では、-library オプションが明示的にコマンドに指定されていません。標準モード (デフォルトのモード) では、-library のデフォルトの設定が Cstd,Crun であるため、-library オプションを明示的に指定する必要はありません。

あるいは、-xnolib コンパイラオプションも使用できます。-xnolib オプションを指定すると、ドライバは自動的には -l オプションを ld に渡しません。次の例は、Solaris 8 または Solaris 9 オペレーティングシステムで libCrun と静的に、libm および libc と動的にリンクする方法を示します。


example% CC test.c- xnolib- lCstd- Bstatic- lCrun- Bdynamic lm- lc

-l オプションの順序は重要です。-lCstd-lCrun、および -lm オプションは、-lc の前に指定します。

ほかのライブラリにリンクする CC オプションもあります。そうしたライブラリへのリンクも -xnolib によって行われないように設定できます。たとえば、-mt オプションを指定すると、CC ドライバは、-lthreadld に渡します。 これに対し、-mt-xnolib の両方を使用すると、CC ドライバは ld-lthread を渡しません。詳細は、「A.2.146 -xnolibを参照してください。ld については、Solaris に関するマニュアル『リンカーとライブラリ』を参照してください。

12.6 共有ライブラリの使用

C++ コンパイラには、次の共有ライブラリが含まれています。

プログラムにリンクされた各共有オブジェクトは、生成される実行可能ファイル (a.out ファイル) に記録されます。 この情報は、実行時に ld.so が使用して動的リンク編集を行います。ライブラリコードをアドレス空間に実際に組み込むのはあとになるため、共有ライブラリを使用するプログラムの実行時の動作は、環境の変化、つまり、ライブラリを別のディレクトリに移動することに影響を受けます。たとえば、プログラムが /opt/SUNWspro/liblibcomplex.so.5 とリンクされている場合、あとで libcomplex.so.5 ライブラリを /opt2/SUNWspro/lib に移動すると、このバイナリコードを実行したときに次のメッセージが表示されます。


ld.so: libcomplex.so.5: ファイルもディレクトリもありません

ただし、環境変数 LD_LIBRARY_PATH に新しいライブラリの ディレクトリを設定すれば、古いバイナリコードを再コンパイルせずに実行できます。

C シェルでは次のように入力します。


example% setenv LD_LIBRARY_PATH \
/opt2/SUNWspro/release/lib:${LD_LIBRARY_PATH}

Bourne シェルでは次のように入力します。


example$ LD_LIBRARY_PATH=\
/opt2/SUNWspro/release/lib:${LD_LIBRARY_PATH}
example$ export LD_LIBRARY_PATH

注 –

release は、コンパイラソフトウェアのそれぞれのリリースによって異なります。


LD_BINARY_PATH には、ディレクトリのリストが含まれています。 ディレクトリは通常コロンで区切られています。C++ プログラムを実行すると、動的ローダーがデフォルトディレクトリより前に LD_BINARY_PATH のディレクトリを検索します。

実行可能ファイルにどのライブラリが動的にリンクされるのかを知るには、ldd コマンドを使用します。


example% ldd a.out

共有ライブラリを移動することはめったにないので、この手順が必要になることはほとんどありません。


注 –

共有ライブラリを dlopen で開く場合は、RTLD_GLOBAL を使用しないと例外が機能しません。


共有ライブラリの詳しい使い方については、『リンカーとライブラリ』を参照してください。

12.7 C++ 標準ライブラリの置き換え

ただし、コンパイラに添付された標準ライブラリを置き換えることは危険で、必ずしもよい結果につながるわけではありません。基本的な操作としては、コンパイラに添付されている標準のヘッダーとライブラリを無効にして、新しいヘッダーファイルとライブラリが格納されているディレクトリとライブラリ自身の名前を指定します。

コンパイラは、標準ライブラリの STLport 実装をサポートします。詳細は、「13.3 STLport」を参照してください。

12.7.1 置き換え可能な対象

ほとんどの標準ライブラリおよびそれに関連するヘッダーは置き換え可能です。 たとえば libCstd ライブラリを別のものに置き換える場合は、次の関連するヘッダーも置き換える必要があります。


<algorithm> <bitset> <complex> <deque> <fstream <functional> <iomanip> <ios> <iosfwd> <iostream> <istream> <iterator> <limits> <list> <locale> <map> <memory> <numeric> <ostream> <queue> <set> <sstream> <stack> <stdexcept> <streambuf> <string> <strstream> <utility> <valarray> <vector>

ライブラリの置き換え可能な部分は、いわゆる「STL」と呼ばれているもの、文字列クラス、iostream クラス、およびそれらの補助クラスです。このようなクラスとヘッダーは相互に依存しているため、それらの一部を置き換えるだけでは通常は機能しません。一部を変更する場合でも、すべてのヘッダーと libCstd のすべてを置き換える必要があります。

12.7.2 置き換え不可能な対象

標準ヘッダー <exception><new>、および <typeinfo> は、コンパイラ自身とlibCrun に密接に関連しているため、これらを置き換えることは安全ではありません。ライブラリ libCrun は、コンパイラが依存している多くの「補助」関数が含まれているため置き換えることはできません。

C から派生した 17 個の標準ヘッダー (<stdlib.h><stdio.h><string.h> など) は、Solaris オペレーティングシステムと基本 Solaris 実行時ライブラリ libc に密接に関連しているため、これらを置き換えることは安全ではありません。これらのヘッダーの C++ 版 (<cstdlib><cstdio><cstring> など) は基本の C 版のヘッダーに密接に関連しているため、これらを置き換えることは安全ではありません。

12.7.3 代替ライブラリのインストール

代替ライブラリをインストールするには、まず、代替ヘッダーの位置と libCstd の代わりに使用するライブラリを決定する必要があります。理解しやすくするために、ここでは、ヘッダーを /opt/mycstd/include にインストールし、ライブラリを /opt/mycstd/lib にインストールすると仮定します。ライブラリの名前は libmyCstd.a であると仮定します。なお、ライブラリの名前を lib で始めると後々便利です。

12.7.4 代替ライブラリの使用

コンパイルごとに -I オプションを指定して、ヘッダーがインストールされている位置を指示します。さらに、 -library=no%Cstd オプションを指定して、コンパイラ独自のバージョンの libCstd ヘッダーが検出されないようにします。次に例を示します。


example% CC -I/opt/mycstd/include -library=no%Cstd... (コンパイルの場合)

-library=no%Cstd オプションを指定しているため、コンパイル中、コンパイラ独自のバージョンのヘッダーがインストールされているディレクトリは検索されません。

プログラムまたはライブラリのリンクごとに -library=no%Cstd オプションを指定して、コンパイラ独自の libCstd が検出されないようにします。 さらに、-L オプションを指定して、代替ライブラリがインストールされているディレクトリを指示します。 さらに、-l オプションを指定して、代替ライブラリを指定します。次に例を示します。


example% CC -library=no%Cstd -L/opt/mycstd/lib -lmyCstd... (リンクの場合)

あるいは、-L-l オプションを使用せずに、ライブラリの絶対パス名を直接指定することもできます。次に例を示します。


example% CC -library=no%Cstd /opt/mycstd/lib/libmyCstd.a... (リンクの場合)

-library=no%Cstd オプションを指定しているため、リンク中、コンパイラ独自のバージョンの libCstd はリンクされません。

12.7.5 標準ヘッダーの実装

C には、<stdio.h><string.h><stdlib.h> などの 17 個の標準ヘッダーがあります。これらのヘッダーは Solaris オペレーティングシステムに標準で付属しており、/user/include に置かれています。C++ にも同様のヘッダーがありますが、さまざまな宣言の名前が大域の名前空間と std 名前空間の両方に存在するという条件が付加されています。version 8 より前のリリースの Solaris オペレーティングシステムの C++ コンパイラでは、/usr/include ディレクトリにあるヘッダーはそのまま残して、独自のバージョンのヘッダーを別に用意しています。

また、C++ には、C 標準ヘッダー (<cstdio><cstring><cstdlib> など) のそれぞれについても専用のバージョンがあります。 C++ 版の C 標準ヘッダーでは、宣言名は std 名前空間にのみ存在します。C++ には、32 個の独自の標準ヘッダー (<string><utility><iostream> など) も追加されています。

標準ヘッダーの実装で、C++ ソースコード内の名前がインクルードするテキストファイル名として使用されているとしましょう。たとえば、標準ヘッダーの <string> (または <string.h>) が、あるディレクトリにある string (または string.h) というファイルを参照するものとします。この実装には、次の欠点があります。

こうした問題を解決するため、コンパイラの include ディレクトリには、ヘッダーと同じ名前を持つファイルと、一意の接尾辞 .SUNWCCh を持つ、そのファイルへのシンボリックリンクが含まれています。SUNW はコンパイラに関係するあらゆるパッケージに対する接頭辞、CC は C++ コンパイラの意味、.h はヘッダーファイルの通常の接尾辞です。 つまり <string> と指定された場合、コンパイラは <string.SUNWCCh> と書き換え、その名前を検索します。接尾辞付きの名前は、コンパイラ専用の include ディレクトリにだけ存在します。このようにして見つけられたファイルがシンボリックリンクの場合 (通常はそうである)、コンパイラは、エラーメッセージやデバッガの参照でそのリンクを 1 回だけ間接参照し、その参照結果 (この場合は string) をファイル名として使用します。ファイルの依存関係情報を送るときは、接尾辞付きの名前の方が使用されます。

この名前の書き換えは、2 つのバージョンがある 17 個の標準 C ヘッダーと 32 個の標準 C++ ヘッダーのいずれかを、パスを指定せずに山括弧 < > で囲んで指定した場合にだけ行われます。山括弧の代わりに引用符が使用されるか、パスが指定されるか、ほかのヘッダーが指定された場合、名前の書き換えは行われません。

次の表は、よくある書き換え例をまとめています。

表 12–3 ヘッダー検索の例

ソースコード 

コンパイラによる検索 

注釈 

<string>

string.SUNWCCh

C++ の文字列テンプレート 

<cstring>

cstring.SUNWCCh

C の string.h の C++ 版

<string.h>

string.h.SUNWCCh

C の string.h

<fcntl.h>

fcntl.h

標準 C および C++ ヘッダー以外 

"string"

string

山括弧ではなく、二重引用符 

<../string>

../string

パス指定がある場合 

コンパイラが header.SUNWCCh (header はヘッダー名) を見つけることができなかった場合、コンパイラは、#include 指令で指定された名前で検索をやり直します。たとえば、#include <string> という指令を指定した場合、コンパイラは string.SUNWCCh という名前のファイルを見つけようとします。この検索が失敗した場合、コンパイラは string という名前のファイルを探します。

12.7.5.1 標準 C++ ヘッダーの置き換え

「12.7.5 標準ヘッダーの実装」で説明している検索アルゴリズムのため、「12.7.3 代替ライブラリのインストール」で説明している SUNWCCh 版の代替 ヘッダーを指定する必要はありません。しかし、これまでに説明したいくつかの問題が発生する可能性もあります。その場合、推奨される解決方法は、接尾辞が付いていないヘッダーごとに、接尾辞 .SUNWCCh を持つファイルに対してシンボリックリンクを作成することです。つまり、ファイルが utility の場合、次のコマンドを実行します。


example% ln -s utility utility.SUNWCCh

utility.SUNWCCh というファイルを探すとき、コンパイラは 1 回目の検索でこのファイルを見つけます。 そのため、utility という名前のほかのファイルやディレクトリを誤って検出してしまうことはありません。

12.7.5.2 標準 C ヘッダーの置き換え

標準 C ヘッダーの置き換えはサポートされていません。それでもなお、独自のバージョンの標準ヘッダーを使用したい場合、推奨される手順は次のとおりです。

たとえば、<stdio.h><cstdio> の代替ヘッダーとして stdio.h と cstdio を使用するとします。stdio.hcstdio をディレクトリ /myproject/myhdr に置きます。このディレクトリ内で、次のコマンドを実行します。


example% ln -s stdio.h stdio.h.SUNWCCh
example% ln -s cstdio cstdio.SUNWCCh

コンパイルのたびに、オプション -I/myproject/mydir を使用します。

警告: