• ベストアンサー

Unix上C++でのdllとインポートライブラリの関係

こんにちわ。 いつも教えてgooにお世話になっているorange_pieです。 UNIX上のC++で作成した自作ライブラリをdllにして配布したいのですが、 Unixでの基本的な考え方を教えてください。 (1)Unix上ではDLLの標準的な名称は”libxxxx.so”とするのが普通ですか?  ※この形式ならLD_LIBRARY_PATH環境変数が検索してくれる。。。 (2)通常、DLLにする場合、インポートライブラリ(.lib)と実際のライブラリ(.so)を作成して、使用する側はインポートライブラリのみをリンクするのでしょうか? (3)配布されたdllを使う側では、Link時にインポートライブラリをリンクして、関連インクルードファイルをインクルードするだけで使えるのでしょうか? (4)上記の(2)のように、インポートライブラリとライブラリの実態を作成する為のコンパイルオプションが見つかりません。(ldのmanを見たのですが、意味がわからないと言うか。。。。。) この質問は、自作ライブラリからlibxxx.soという形のオブジェクトファイルを作り、別プログラムからこのlibxxxをコンパイルオプション(-l)でリンクしてみたら正しく動作したのですが、これでは結局ライブラリの本体が一緒にリンクされている様子で、出来上がった実行形式のファイルサイズが静的ライブラリとしてリンクした時と同じ大きさになっていることに疑問を抱いてしまったものです。  この状態でも、ライブラリの方だけコンパイルしなおして実行すると ちゃんとライブラリの変更点は反映されるので問題は無いのですが、 これでもダイナミックリンク・ライブラリと呼べるのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.3

# すっごく暇ってわけではないんですが :-) > -Wl,-B,dynamic -lclntsh -ldl -lm -lnsl -lsocket -lrt -lpthread > > この中の”-B, dynamic ”の辺りが「ライブラリをダイナミックにリンクするよ」ってことだったのでしょうか? man ld の -l と -B のところを読めば分かると思いますが、大体、そういうことです。 -B dynamic の場合(普通は、こっちがデフォルト)には -lxxx の指定で libxxx.so を探して、無ければ、libxxx.a を探します。-B static の場合には libxxx.so を 対象にしません。 参考URLには solaris の AnswerBook を紹介しておきます。 > ということも考慮に入れると、arコマンドで作ったアーカイブもDLLもリンクオプションで-B dynamic とすれば、実行時にリンクできる。(のかな?) いやいや。静的なライブラリ、っつう位ですから、静的なリンクにしか使え ません。 .a も .so も「ライブラリ」って名前がつきますけれど、.a はアーカイブファイル なので、tar の出力ファイルの方に似ています。.so の方は、実行形式のヘッダを 持ち ELF というフォーマットのファイルで実行バイナリの方に似ています。 > で、他人に提供するのにアーカイブとDLLのどちらが適しているかというと、 > 関数などが増えた場合以外はどちらでも同じ(という感じ?なのかな?) その「他人」の環境次第なんですが、相手の OS やバージョンが特定できないと 静的なアーカイブの方が、利用できる可能性が少し広いです(ソース提供には 遠く及ばないですが)。 > arコマンドは、複数のオブジェクト(.o)を追加することで作成しなおすことができるが、DLLはライブラリ構成プログラムをリコンパイルする必要がある。 リコンパイルではなく、再リンクです。 後、共有ライブラリの場合には、あまり小さく刻んでしまうとロードの時間が 気になり出すので、ひとつのファイルの単位をどうするかを悩むときがあり ます。 最後に、No.2 の回答にあるように unix をひと括りにして、.so が普通、と 言うのは、ちょっと大雑把すぎました。他の質問のことが頭にあったもので orange_pie さんが使っている環境を暗に想定してました。 十年くらいさかのぼっただけで共有ライブラリが扱えない unix なんてのは、 ごろごろしてましたし。

参考URL:
http://docs.sun.com:80/ab2/coll.153.4/REFMAN1/@Ab2PageView/116238?Ab2Lang=ja&Ab2Enc=shift_jis
orange_pie
質問者

お礼

本当にお忙しいのに、ありがとうございます。いつもいつも。。。 (。・_・。) >a も .so も「ライブラリ」って名前がつきますけれど、.a はアーカイブファイル >なので、tar の出力ファイルの方に似ています。.so の方は、実行形式のヘッダを 持ち ELF というフォーマットのファイルで実行バイナリの方に似ています。 すばらしいです!!すっきり解決。すんなり納得。もう混乱しません。 どうしたら、こんなに正しい知識を幅広くお持ちになれるんでしょう。。。 もしかして、教授さん? これからは、ぷろくまさんと呼ばせていただきます。(私だけ。) 参考URLは、Solaris上でmanコマンドを叩いたのと同じ情報のようですね。 これなら、いちいちターミナルからSolarisに接続しなくても良いので早速「お気に入り」に入れちゃいました。 本当にありがとうございました。

その他の回答 (2)

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.2

a-kumaさんの回答でだいたい良いのですが、 > (1)Unix上ではDLLの標準的な名称は”libxxxx.so”とするのが普通ですか? これはUNIXの種類によります。SolarisやLINUXではその通りですが、HP-UXなどでは libxxx.shになったりします。 あとlibxxx.aは静的ライブラリです。-B dynamic というリンクオプションが無ければ こちらがリンクされます。-B static と明示的に指定することもできます。

orange_pie
質問者

お礼

は~。なるほど~。です。 ”.a”と言ったら一般的に静的だと思えばよいのですね。 それならばやはり”.so”です。 ちなみにSolarisでの開発なので、libxxxx.soと言う形にしました。 このようなルールって、厳密に決められている訳ではなくて ”通常、こうだよね”というような、経験者の方に聞かなければ分からないことが多いような気がします。 無事にdllを作成して、配布できるまでに至りました。 みなさんのおかげです。 本当にありがとうございました。

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.1

> (1)Unix上ではDLLの標準的な名称は”libxxxx.so”とするのが普通ですか? そうです。 OS によっては、libxxx.so は、libxxx.so.バージョン番号 というファイルへの シンボリックリンクになってたりしますが、ローダが *.so というファイルを 探しに行くことが基本なのは一緒です。 > (2)通常、DLLにする場合、インポートライブラリ(.lib)と実際のライブラリ(.so)を作成して、使用する側はインポートライブラリのみをリンクするのでしょうか? unix では、インポートライブラリなんて不細工なものは気にしなくても良いです。 直接、共有ライブラリがリンクできることは経験した通り。 > (3)配布されたdllを使う側では、Link時にインポートライブラリをリンクして、関連インクルードファイルをインクルードするだけで使えるのでしょうか? インポートライブラリなんてものが要らないのは (2) の回答で書いた通り。 インクルードファイルが必要なのは、C/C++ で共通の定数やプロトタイプが 記述してあるから、という理由なだけで、「DLLを使う」ための必須の条件では ありません。 > (4)上記の(2)のように、インポートライブラリとライブラリの実態を作成する為のコンパイルオプションが見つかりません。(ldのmanを見たのですが、意味がわからないと言うか。。。。。) というわけで、unix のマニュアルを見ても永遠に分かることはないでしょう。 > これでは結局ライブラリの本体が一緒にリンクされている様子で、出来上がった実行形式のファイルサイズが静的ライブラリとしてリンクした時と同じ大きさになっている ちょっと信じられません。 > ライブラリの方だけコンパイルしなおして実行するとちゃんとライブラリの変更点は反映される ということから、共有ライブラリとしてはきちんと作成されているようです。 多分、静的なライブラリをリンクしたつもりになっているだけで、動的な ライブラリがリンクされているはずです。 ld の man などに、libxxx.a と libxxx.so の両方が存在しているときの 動作について説明があるはずです。libxxx.so を削除してしまってから もう一度、リンクをしてみてください。 実際にモジュールの参照が静的に解決されているかどうかは、nm という コマンドで確認することが出来ます。

orange_pie
質問者

お礼

なるほど~。 インポートライブラリって、確かOS/2だかWindowsだかでDLLを作った時に「作れ!!」と言われたような気がして、Unixでも「そうなのかな~」と漠然と思ってしまいました。気にしなくてよかったのですね。 それから、 >多分、静的なライブラリをリンクしたつもりになっているだけで、 >動的なライブラリがリンクされているはずです。 についてですが、静的なライブラリをリンクしていたつもりのMakefileを見直して見たところ、Linkオプションに以下のように指定してありました。 -Wl,-B,dynamic -lclntsh -ldl -lm -lnsl -lsocket -lrt -lpthread この中の”-B, dynamic ”の辺りが「ライブラリをダイナミックにリンクするよ」ってことだったのでしょうか? そうだとすると、「静的にリンクしていたつもりで、実はもともと動的にリンクしていた」ということになり、サイズが同じという疑問が解けてすっきりします。 ん? それでは、".a”と”.so”の違いってなんでしょう? 以前、くまさんが教えてくださった、 >ar コマンドで作成されるアーカイブとは違って、DLL は「リンクされたもの」 ですから、必要なオブジェクトファイルが増減したときには、追加・削除では なく、常に再リンクをすることに注意してください。 ということも考慮に入れると、arコマンドで作ったアーカイブもDLLもリンクオプションで-B dynamic とすれば、実行時にリンクできる。(のかな?) で、他人に提供するのにアーカイブとDLLのどちらが適しているかというと、 関数などが増えた場合以外はどちらでも同じ(という感じ?なのかな?) arコマンドは、複数のオブジェクト(.o)を追加することで作成しなおすことができるが、DLLはライブラリ構成プログラムをリコンパイルする必要がある。 ということになるのでしょうか?  Unix的に美しいのは、.soですよね。きっと。 あ~。長々とすみません。 いろいろありがとうございます。 くまさんもお忙しいでしょうから、お返事はすっごく暇なときがあったらで 良いです。お返事がなくても自分でアーカイブとDLLの違いくらいは理解できるように探求します。 本当にありがとうございました。