Linux 環境で gcc を用いて共有ライブラリを作成する際の基本的なことをメモしておきます。 g++ でも手順は同じです。
サンプルとして次の func.c を準備します。
int add(int a, int b)
{
return a+b;
}
二つの整数値を足して、その値を返すだけの簡単な関数 add() を定義しています。
オブジェクトファイルの静的リンク
func.c
を -c
(コンパイルのみ)でビルドすると、オブジェクトファイル func.o
が作成できます。
$ gcc -c func.c
呼び出し元から静的リンクするには、次のように一緒にビルドするだけです。
$ gcc -o app app.c func.o
$ ./app
a+b=8
複数のオブジェクトファイルをまとめて、静的ライブラリにする
a.c
、b.c
、c.c
のそれぞれがあった場合、アーカイブコマンド ar
によってライブラリをまとめることができます。
$ gcc -c a.c b.c c.c
$ ar r libabc.a a.o b.o c.o
まとめられた libabc.a
はただのアーカイブファイルですので、ranlib
でライブラリ内のインデックスを構築してあげます。
$ ranlib libabc.a
libabc.a
を使ったソースのビルドはこんな具合です。
$ gcc app.c libabc.a
共有ライブラリの動的リンク
func.c
を共有ライブラリ libfunc.so
としてビルドします。
$ gcc -shared -o libfunc.so func.c
-shared
オプションをつけるだけです。このライブラリを使うには、次のような app.c
を準備して
#include <stdio.h>
int main()
{
printf("a+b=%d\n", add(3, 5));
return 0;
}
まとめてビルドします。ヘッダファイルも不要です。
$ gcc -o app app.c libfunc.so
$ LD_LIBRARY_PATH=. ./app
a+b=8
ライブラリパスをカレントに指定して実行すると、ちゃんと libfunc.so
の機能が使えていることが分かります。 簡単ですねー。
共有ライブラリの動的ロード
dlopen(3)
を用います。ライブラリ側に特殊なコーディングは必要ありません。上記のように共有ライブラリとしてビルドすればOKです。
#include <stdio.h>
#include <dlfcn.h>
int main(void)
{
void *handle
= dlopen("./libfunc.so", RTLD_LAZY); // ライブラリを開く
int (*add)(int, int) = dlsym(handle, "add"); // 関数ポインタを取ってくる
printf("a+b=%d\n", (*add)(3, 5)); // 関数を叩く
dlclose(handle); // ライブラリを閉じる
}
このコードは次のようにビルドします。
$ gcc -rdynamic -ldl -o app2 app2.c
$ ./app2
a+b=8
-ldl
は動的ロードライブラリへのリンクです。
参考リンク
その他、留意点などは次のページを参考にしてください。
- Linux の共有ライブラリを作るとき PIC でコンパイルするのはなぜか
- 外部から参照可能なシンボルを制限する
- C++における関数のオーバーロード対策
- 共有ライブラリーを解剖する
- ライブラリ – Wikipedia
- 位置独立コード – Wikipedia
- 第 15 章 ライブラリの構築 (Oracle Solaris Studio 12.2: C++ ユーザーズガイド)
- Linux 動的ライブラリーの徹底調査
- Linux の共有ライブラリを作るとき PIC でコンパイルするのはなぜか – bkブログ
- 動的リンクと静的リンクの実行時のコスト差について – 中年高卒プログラマの遠吠え
[…] navigation ← ライブラリを作成、使用する FastCGI+lighttpd で C プログラムを動かす […]
[…] 先日、覚え書きとして「ライブラリを作成、使用する」を書きましたが、同じ事を Microsoft Windows と Microsoft Visual Studio で行うためのメモです。 […]