忍者ブログ
MASTER →  ADMIN / NEW ENTRY / COMMENT
現代魔法(nearly equal 情報技術)を勉強中な人のメモ(チラシの裏)
/ 2024/04/26 (Fri) / 編集
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

/ 2010/01/02 (Sat) / 編集
Macでの共有・静的・動的ライブラリの作り方メモ
Program Library HOWTOUnix ソフトウェアの Darwin と Mac OS X への移植を参照。


前準備

とりあえず「DYLD_LIBRAY_PATH」(Linuxでいうところの「LD_LIBRAY_PATH」)に「.」を追加しておく。

あとはサンプルプログラムを用意しとこう!

libhello.h

void hello(void);

libhello.c

#include  <stdio.h>

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

demo_use.c

#include "libhello.h"

int main(void) {
	hello();
	return 0;
}
オブジェクトファイルを生成しておく
gcc -Wall -g -c demo_use.c -o demo_use.o

demo_dynamic.c

/*
 * 動的にライブラリをロードするルーチン用に 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;
}
オブジェクトファイルを生成しておく
gcc -Wall -g -c demo_dynamic.c -o demo_dynamic.o

静的ライブラリ (Static Library)

「.a」なライブラリ。
各プログラムとリンクされていて、他のプログラムと共有することはできない。

普通にオブジェクトファイルを生成
gcc -Wall -g -c -o libhello.o libhello.c
arコマンドで静的ライブラリを生成
ar rcs libhello.a libhello.o
では、実行ファイルを生成
gcc -g -o demo_use_static demo_use.o -L. -lhello


共有ライブラリ (Shared Library)

「.dylib」(Linuxでは「.so」)なライブラリ。複数のプログラムが同時に同じライブラリを使用することができる。
Linuxとかではローダブル・モジュールと一体になってるけどMac(というかDarwin)では別々。

位置独立コード (PIC: Position Independent Code) の生成のために「-fPIC」、リンカは"共通"のシンボルを共有ライブラリ内に持つことは認めないので「-fno-common」をつけてオブジェクトファイルを生成
gcc -fno-common -fPIC -Wall -g -c libhello.c
共有ライブラリなので「-dynamiclib」、インストール先を明示しないといけないので「-install_name フルパス」、バージョンの指定もしとく。 ちなみに、バージョンが2.4.5の場合、2 が主リビジョン (非互換の API 変更), 4 が副リビジョン (後方互換な API の変更),5 がバグ修正(teeny)リビジョン(完全に互換性のある変更)らしい、今回の例ではバージョンは0.0.0なので、互換バージョンは「-compatibility_version 0.0」、現在バージョンは「-current_version 0.0.0」と指定する。
gcc -g -dynamiclib -install_name libhello.0.0.0.dylib -compatibility_version 0.0 -current_version 0.0.0 -o libhello.0.0.0.dylib libhello.o -lc
「lc」がついているのはlibhello.cでstdio.hを使っており、libcに依存しているから。

インストールパスは「-install_name」で指定したので、ldconfigは要らない。なのでsonameもlinker nameもlnで作ります。
ln -s libhello.0.0.0.dylib libhello.0.dylib
ln -s libhello.0.0.0.dylib libhello.dylib
では、実行ファイルを生成
gcc -g -o demo_use_shared demo_use.o -L. -lhello


ローダブル・モジュール (Dinamics Library)

「.so」なライブラリ、Apple的には「.bundle」とかが推奨らしい。 プログラム中で「dllfunc.h」の「dlopen」などを使って動的に読み込み&クローズできる。
frameworkに使われているやつ。

位置独立コード (PIC: Position Independent Code) の生成のために「-fPIC」、リンカは"共通"のシンボルを共有ライブラリ内に持つことは認めないので「-fno-common」をつけてオブジェクトファイルを生成
gcc -fno-common -fPIC -Wall -g -c libhello.c
動的ライブラリなので「-bundle」、後方互換のために「-flat_namespace」、ホストプログラムのシンボルを使うため「-undefined suppress」
gcc -bundle -flat_namespace -undefined suppress -o libhello.so libhello.o
では、実行ファイルを生成。内部で呼びだすのでlibhelloは必要ない、そのかわりに「dllfunc.h」を使うための「libdl」をリンクしておく。
gcc -g -o demo_use_dynamic demo_dynamic.o -ldl


拍手[1回]

PR
忍者ブログ [PR]