(勉強中なので内容の正確さは保証しない。元々すべてがそうだけど。)
(ダイナミック, 動的, 実行時) ローディングとかモジュールとか、 共有ライブラリィとか、 ぼんやり分かっているようなつもりでいたけれど、 勉強が必要そうに感じたので。
言葉の使い方が、OS によっても違ったりするそうである。 特に Mac は他とは違い独特とか。 以下は、Mac で使うことを念頭にまとめる。
(このパラグラフは自分勝手説明かも…言い訳をすると、 元々どの OS でも通用するような用語が決まっていないらしく、 仕方がないのではないか…) 一つの実行プログラムは、複数のソースプログラムから作るのが普通で、 それを組み合わせる仕方に、 リンク (静的リンクと動的リンクがある) と実行時のロードがある。 動的リンクは、実行時にライブラリィをロードすると言っても良さそうで、 言葉ではっきり区別しにくいところがある。 Mac でははっきり区別するそうで、 それを独特という人がいるけれど、 説明をする場合は、区別する方が説明しやすいので、以下ではそうする。
以下の内容は、 「Macでのライブラリの作り方」 を読んで理解したもので、説明プログラムもそこのを拝借している。 プログラムの名前を変えたり、説明の順序を入れ替えているけれど、 それで何か間違いが入っているかもしれない (その場合はすみません)。
動的リンクでは、実行形式を作る「リンク」の段階で、 どのライブラリィとリンクするか名前を決めなければならない (後から同じ名前の別ライブラリィに差し替える、という裏技はできるけど)。
これに対して、動的ロードでは、 プログラムの実行時にどのモジュールをロードするか決めれば良い。 実行形式を作るときに、ロードするモジュールの名前を決める必要はない。
動的なモジュールの拡張子として、.so が使われることが多いが、 Macの場合 Apple は .bundle を推奨しているそうだ。
リンクの実例
繰り返しになるが、以下のプログラムは丸々拝借している。
リンクには二種類の方法があるが、どちらをするにしても、 ソース・プログラムは共通で済む。
libhello.h |
/Users/mk/.tex-inputs/staticlink_dynamiclink_dynamicload/libhello.h |
libhello.c |
/Users/mk/.tex-inputs/staticlink_dynamiclink_dynamicload/libhello.c |
main_link.c |
/Users/mk/.tex-inputs/staticlink_dynamiclink_dynamicload/main_link.c |
メインのプログラムの方のコンパイルの仕方は共通である。
gcc -Wall -g -c main_link.c -o main_link.o |
静的なリンク (比較的一般的なやり方) |
gcc -Wall -g -c -o libhello.o libhello.c ar rcs libhello.a libhello.o gcc -g -o main_static main_link.o -L. -lhello |
動的なリンク (これは自分ではやったことがない) |
gcc -fno-common -fPIC -Wall -g -c libhello.c 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 ln -s libhello.0.0.0.dylib libhello.0.dylib ln -s libhello.0.0.0.dylib libhello.dylib #rm -f libhello.a gcc -g -o main_dynamic main_link.o -L. -lhello以上は macOS の場合であるが、Solaris や Linux では、 .dylib でなくて .so と言う拡張子を使う。 |
動的ロードの実例 繰り返しになるが、以下のプログラムは丸々拝借している。
モジュール (「ライブラリィ」) 側のソース・プログラムは上と同じで良い。 まずモジュール (libhello.so) を作ってみる。
Macでの動的モジュールの作成 |
gcc -fno-common -fPIC -Wall -g -c libhello.c gcc -bundle -flat_namespace -undefined suppress -o libhello.so libhello.o |
次はこれを呼び出す側だが、これはちょっと面倒である。
main_load.c |
/Users/mk/.tex-inputs/staticlink_dynamiclink_dynamicload/main_load.c |
gcc -Wall -g -c main_load.c -o main_load.o |
gcc -g -o main_load main_load.o -ldl |
どのモジュールをロードするかは、 この場合 main_load.c の中に書かれているわけだが、 その気になれば "libhello.so" という文字列を実行時にユーザーに決めさせることも出来るわけだ ("libbye.so" とか)。 確かにダイナミック・リンクとダイナミック・ロードは違う概念だ。
FreeFem++ で plotPDF() を使う場合、 実行形式 (FreeFem++) の方は先に作ってあって、 plotPDF() の入っているモジュールは後から作って、 どれをロードするか .edp の中で指定できる (それこそユーザーに文字列入力させて選ぶようにもできる)、 と言うことだ。