6. 例

三つの方法 (静的ライブラリ、共有ライブラリ、動的ライブラリ) 全ての例を以下に挙げます。 libhello.c ファイルは簡単なライブラリで、そのヘッダファイルとして libhello.h があります。 demo_use.c ファイルは、libhello ライブラリを呼び出す簡単なプログラムです。 続けて、コメント付きのスクリプト (script_static と script_dynamic) を示します。 これらのスクリプトは、libhello ライブラリを静的ライブラリおよび共有ライブラリとして使う方法を示すものです。 さらに demo_dynamic.c と script_dynamic も挙げます。 これらは、共有ライブラリを動的ライブラリとして使う方法を示すものです。

6.1. libhello.c ファイル

  /* libhello.c - ライブラリ使用方法を示します */

  #include <stdio.h>

  void hello(void) {
      printf("Hello, library world.\n");
  }

6.2. libhello.h ファイル

  /* libhello.h - ライブラリ使用方法を示します */

  void hello(void);

6.3. demo_use.c ファイル

  /* demo_use.c -- "hello" ルーチンを直接使用する方法を示します */

  #include "libhello.h"

  int main(void) {
      hello();
      return 0;
  }

6.4. script_static ファイル

  #!/bin/sh
  # 静的ライブラリのデモ

  # 静的ライブラリのオブジェクトファイル libhello-static.o を
  # 作成します。静的ライブラリの例と動的ライブラリの例を明確に
  # 区別するため、libhello-static という名前を使用しています。
  # しかし、オブジェクトファイルや静的ライブラリの名前に
  # "-static" を使う必要はありません。

  gcc -Wall -g -c -o libhello-static.o libhello.c

  # 静的ライブラリを作成します。

  ar rcs libhello-static.a libhello-static.o

  # この段階で、libhello-static.a をどこか他の場所へコピーして
  # 使用することもできますが、デモが目的なので、libhello-static.a
  # ライブラリはカレントディレクトリ内に置いたままにします。

  # demo_use プログラムをコンパイルします。

  gcc -Wall -g -c demo_use.c -o demo_use.o

  # demo_use プログラムを作成します。-L. オプションにより、プロ
  # グラム作成中、カレントディレクトリ "." が検索されます。この
  # コマンドにより、libhello-static 内の関連するオブジェクト
  # ファイルが demo_use_static に組み込まれます。

  gcc -g -o demo_use_static demo_use.o -L. -lhello-static

  # プログラムを実行します。

  ./demo_use_static

6.5. script_shared ファイル

  #!/bin/sh
  # 共有ライブラリのデモ

  # 共有ライブラリのオブジェクトファイル libhello.o を作成します。

  gcc -fPIC -Wall -g -c libhello.c

  # 共有ライブラリを作成します。libhello は C ライブラリに依存して
  # いるので、C ライブラリとリンクさせるために -lc オプションを使い
  # ます。

  gcc -g -shared -Wl,-soname,libhello.so.0 \
      -o libhello.so.0.0 libhello.o -lc

  # この段階で、libhello.so.0.0 を、/usr/local/lib 等のどこかの
  # ディレクトリへコピーしてもかまいません。

  # シンボリックリンクを修正するため、ldconfig を呼び出す必要が
  # あります。

  # soname を設定します。単に、
  #
  #   ln -sf libhello.so.0.0 libhello.so.0
  #
  # を実行するだけでもよいですが、ldconfig にやってもらいましょう。

  /sbin/ldconfig -n .

  # linker name を設定します。設定手順をより洗練させるならば、既に
  # linker name が存在するかどうかを調べ、存在する場合には linker
  # name を残すべきか否かを確認する必要があります。

  ln -sf libhello.so.0 libhello.so

  # demo_use プログラムをコンパイルします。

  gcc -Wall -g -c demo_use.c -o demo_use.o

  # demo_use プログラムを作成します。-L. オプションにより、プロ
  # グラム作成中、カレントディレクトリ "." が検索されます。これは、
  # プログラム実行時にカレントディレクトリ "." が検索されるという
  # 意味ではないので注意してください。

  gcc -g -o demo_use demo_use.o -L. -lhello

  # プログラムを実行します。LD_LIBRARY_PATH を使って、どこに共有
  # ライブラリが存在するかをプログラムに教える必要があることに
  # 注意してください。

  LD_LIBRARY_PATH="." ./demo_use

6.6. demo_dynamic.c ファイル

  /*
   * demo_dynamic.c
   *
   * 動的ローディングと "hello" ルーチンの使用方法を示します
   */

  /*
   * 動的にライブラリをロードするルーチン用に dlfcn.h が必要
   */
  #include <dlfcn.h>

  #include <stdlib.h>
  #include <stdio.h>

  /*
   * "libhello.h" をインクルードする必要がないことに注意して
   * ください。但し、関連情報を指定する必要があります。
   * dlsym() で取得する値を保持するための型が必要です。
   */

  /*
   * "simple_demo_function" 型は、引数を取らず、何も値を返さない
   * 関数を示しています。
   */

  typedef void (*simple_demo_function)(void);

  int main(void) {
      const char *error;
      void *module;
      simple_demo_function demo_function;

      /* 動的ライブラリをロードする */
      module = dlopen("libhello.so", RTLD_LAZY);
      if (!module) {
          fprintf(stderr, "libhello.so をオープンできませんでした: %s\n", dlerror());
          exit(1);
      }

      /* シンボルを取得する */
      dlerror();
      demo_function = dlsym(module, "hello");
      if ((error = dlerror())) {
          fprintf(stderr, "hello が見つかりませんでした: %s\n", error);
          exit(1);
      }

      /* 動的ライブラリ内の関数を呼び出す */
      (*demo_function)();

      /* 全て終了。きちんとクローズする */
      dlclose(module);

      return 0;
  }

6.7. script_dynamic ファイル

  #!/bin/sh
  # 動的ライブラリのデモ

  # libhello.so とその関連ファイルが既に作成されているものと
  # 仮定しています (共有ライブラリのデモを参照してください)。

  # demo_dynamic プログラムファイルをオブジェクトファイルへ
  # コンパイルします。

  gcc -Wall -g -c demo_dynamic.c

  # demo_use プログラムを作成します。このプログラムが使用する
  # 唯一の特別なライブラリは、プログラム起動後までロードされ
  # ないので、動的ライブラリをどこに探しにいけばよいかを教える
  # 必要はありません。但し、動的ライブラリをロードするための
  # ライブラリを含めるのに、-ldl オプションが必要となります。

  gcc -g -o demo_dynamic demo_dynamic.o -ldl

  # プログラムを実行します。LD_LIBRARY_PATH を使って、どこに
  # 動的ライブラリが存在するかをプログラムに教える必要がある
  # ことに注意してください。

  LD_LIBRARY_PATH="." ./demo_dynamic