こんにちわ。
いつも教えて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)でリンクしてみたら正しく動作したのですが、これでは結局ライブラリの本体が一緒にリンクされている様子で、出来上がった実行形式のファイルサイズが静的ライブラリとしてリンクした時と同じ大きさになっていることに疑問を抱いてしまったものです。
 この状態でも、ライブラリの方だけコンパイルしなおして実行すると
ちゃんとライブラリの変更点は反映されるので問題は無いのですが、
これでもダイナミックリンク・ライブラリと呼べるのでしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (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/@A …
    • good
    • 0
この回答へのお礼

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

お礼日時:2001/10/10 09:15

a-kumaさんの回答でだいたい良いのですが、


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

は~。なるほど~。です。
”.a”と言ったら一般的に静的だと思えばよいのですね。
それならばやはり”.so”です。
ちなみにSolarisでの開発なので、libxxxx.soと言う形にしました。
このようなルールって、厳密に決められている訳ではなくて
”通常、こうだよね”というような、経験者の方に聞かなければ分からないことが多いような気がします。

無事にdllを作成して、配布できるまでに至りました。
みなさんのおかげです。
本当にありがとうございました。

お礼日時:2001/10/09 17:27

> (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 という
コマンドで確認することが出来ます。
    • good
    • 0
この回答へのお礼

なるほど~。
インポートライブラリって、確か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の違いくらいは理解できるように探求します。
本当にありがとうございました。

お礼日時:2001/10/09 15:37

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QVC++2008でインポートライブラリのスタティックリンクの設定

VC++2008でインポートライブラリのスタティックリンクの設定
従来のVC++6.0ではプロジェクトのビルド時にインポートライブラリをスタティックリンクさせる場合
「プロジェクト」メニューから「設定」項目を選択し、「プロジェクトの設定」ウィンドウを表示させて、
「リンク」タブをクリックして表示されるページの「オブジェクト/ライブラリモジュール」欄の先頭に、
MyDll.lib(例)とスペースを1つ入力していました。末尾のスペースはMyDll.libとkernel32.libを区切るために必要でした。

これをVC++2008で実現するためにはどの様にしたらいいのですか?
VC++2008の「プロジェクト」メニューを探しても「プロジェクトの設定」ウィンドウがありません。

Aベストアンサー

VC++.NET 2003で確認しましたが、2005でも同様だったので、2008でも変わらないと思います。

(1)「プロジェクト」メニューから「○○○のプロパティ」(○○○はプロジェクト名)を選択。
(2)「構成プロパティ」の「リンカ」の「全般」を選択。
(3)「追加のライブラリディレクトリ」に該当のディレクトリを設定。
(4)「構成プロパティ」の「リンカ」の「入力」を選択。
(5)「追加の依存ファイル」に該当のライブラリファイルを設定。

(3)、(5)は「構成」(Debug、Release等)や「プラットフォーム」(Win32等)の必要なものすべてに付いて行います。

QOpenSSLの共有ライブラリ(libcrypto.so)動的リンクにつきまして

[環境]
Linux version 2.6.9-67.EL
gcc version 3.4.6 (Red Hat 3.4.6-8))

以下のように、OpenSSLの共有ライブラリlibcrypto.soをロードする
プログラムを書いているのですが、

------
#include <stdio.h>
#include <dlfcn.h>
#include <errno.h>

void main(void)
{
void* hSO;
hSO = DLL_OPEN("/usr/local/ssl/lib/libcrypto.so", RTLD_NOW);

if( hSO == NULL )
{
printf("%s\n", dlerror());
}
else
{
// 処理
}
}
------

hSO = DLL_OPEN("/usr/local/ssl/lib/libcrypto.so", RTLD_NOW);
で、NULLが返って来てしまいます。

[dlerror内容]
/usr/local/ssl/lib/libcrypto.so: cannot open shared object file: No such file or directory

しかし、このパスには、シンボリックリンクされたlibcrypto.soファイルが存在します。
試しに、同ディレクトリにあるlibcrypto.so.0.9.8mも試しましたが、同じエラーが出力されました。

パスの指定方法に、何か行う必要があるのでしょうか。

[環境]
Linux version 2.6.9-67.EL
gcc version 3.4.6 (Red Hat 3.4.6-8))

以下のように、OpenSSLの共有ライブラリlibcrypto.soをロードする
プログラムを書いているのですが、

------
#include <stdio.h>
#include <dlfcn.h>
#include <errno.h>

void main(void)
{
void* hSO;
hSO = DLL_OPEN("/usr/local/ssl/lib/libcrypto.so", RTLD_NOW);

if( hSO == NULL )
{
printf("%s\n", dlerror());
}
else
{
// 処理
}
}
------

hSO = DLL_OPEN("/usr/local/ssl/lib/libcrypto....続きを読む

Aベストアンサー

DLL_OPENってdlopenだよね。
libcrypto.soが参照している別のsoファイルが見つからないとか。
やってみたいこと:
1.
RTLD_NOWをRTLD_LAZYにしてみる。これでエラーにならないなら別ファイルが問題だね。
2.
LD_LIBRARY_PATHに/usr/local/ssl/libを追加して、パスを/usr/local/ssl/lib/libcrypto.soでなくてlibcrypto.soで呼んでみる。これで通るようだと絶対パス指定に問題があるか。

QUNIX上でdos.hをインクルード

下記のURLのプログラムらをUNIX(Solaris)上でコンパイルするとdos.hファイルが見つからない,というようなエラーが出ます。これらのプログラムをSolaris上でコンパイルし,実行できるようにするにはどう書き換えればよろしいのでしょうか。課題の一部なのですが宜しくお願いします。
http://www-itolab.ics.nitech.ac.jp/creport/enshu_kadai/src/rec_key_points.c

http://www-itolab.ics.nitech.ac.jp/creport/enshu_kadai/src/rec_angle.c

http://www-itolab.ics.nitech.ac.jp/creport/enshu_kadai/src/robot_simulator.c

Aベストアンサー

#1です。

>このcheck_point(a,b)はコメント扱いになっているのでしょうか。
そうですね。Cでは、/* から */ はコメントです。
これは、IBM-PC用のコードのようです。で、下のほうにある同じ関数が、
NEC PC-9801用のコードのようです。
(IBM-PC用のソースをPC-9801用に移植したものかもしれません)
機能としては、カーソル位置の文字が'*'かどうかを検査するものです。

>また,int86やregsとはなんなのでしょうか。
int86は、Pentiummのご先祖様の8086CPUのソフトウェア割り込みです。
今でもDOSモードで動くと思います。BIOSをCALLする時などに使用します。
(例では、IBM-PCのVIDEO BIOSである INT 10h を呼び出しています)

regsというのは、CPUのレジスタに値をセットするための共用体変数です。
regsにレジスタにセットしたい値をセットして、int86関数をCALLすると、
アセンブラで呼び出すようなことがCで可能になるのです。

サンプル(課題)のソースのコメントアウトされている方の関数(IBM-PC用)を
有効にして、下にある同じ関数名の方(PC-9801用)をコメントアウトして
DOS用のCコンパイラでコンパイル/リンクするとDOSプロンプトで実行できる
と思います。(PC-9801でない普通のWindowsマシンなら)

int86についてはこちらをご参考に。
http://www2.muroran-it.ac.jp/circle/mpc/old/pc98dos/dos/dosinit.html

フリーのDOS用のCコンパイラはこちらからダウンロードできます。
http://www.vector.co.jp/soft/maker/lsi/se001169.html

本題については、Solarisでこの機能(check_point()関数)をどう実現
するかということになろうかと思います。

参考URL:http://www2.muroran-it.ac.jp/circle/mpc/old/pc98dos/dos/dosinit.html

#1です。

>このcheck_point(a,b)はコメント扱いになっているのでしょうか。
そうですね。Cでは、/* から */ はコメントです。
これは、IBM-PC用のコードのようです。で、下のほうにある同じ関数が、
NEC PC-9801用のコードのようです。
(IBM-PC用のソースをPC-9801用に移植したものかもしれません)
機能としては、カーソル位置の文字が'*'かどうかを検査するものです。

>また,int86やregsとはなんなのでしょうか。
int86は、Pentiummのご先祖様の8086CPUのソフトウェア割り込みです。
今で...続きを読む

Q作成したDLLをATL_COM_APPWIZARDで利用する方法について

VC6++のWin32 Dynamic Link LibraryでDLLを作成しました。
DLLはできたのですが、これを利用する方法がわかりません。

ATL COM AppWizardで作成するアプリからDLLのクラスを使いたいのですが、どのようにすれば使えるのでしょうか?

最初のDLL側は
class Test{
Test(){
ShowMessageBox(NULL, "最初のDLL", "呼ばれました", MB_OK);
}
};

というクラスです。

ATL COM Appwizardでは、
どのように記述すれば、DLLのクラスを利用することができるのでしょうか?

Aベストアンサー

DLLを作成しながら利用方法がわからないって、、いったいどうやって
作ったんでしょ^^;^^;

VC6でATLを使うのは、非常にめんどいです。
内容を技術的に把握してないと、まず、つかえません。
また、『DLLのクラスを利用』と記述していますが、
そもそもCOMのDLLはそのような使い方をするものではありません。

普通のCOMでないDLLで、クラスをexportする方法みたいな話ですか?
もう少し具体的な質問でお願いできればと。。

QDLLとexeでのインクルードについて

いつもお世話になっております。DLLでincludeしたものはexeでもincludeしなければならないのか疑問に思っています。
例えば、
DLL側である関数abc()内でWindowsMessage()を使用するために#include<windows.h>とインクルードした場合。
Exe側では関数abc()を使用するためにwindouw.hをインクルードしなければならないのでしょうか。

試してみた所、インクルードしなくてもうまくいったのですがたまたま何かしらでうまくいっていただけかもと不安に思ったので、一般的にはどうなのかと思い質問させていただきました。

Aベストアンサー

「関数を呼んだら、呼んだ先の事は知らない」のがCやC++の良い所でもあり、悪い所でもあります。

以下のような「単純な例」で考えれば「インクルードは不要」だと判るでしょう。

【main.c】
void sub(void);/*sub()が何者なのかを宣言しておく*/
int main(void)
{
sub();
}

【sub.c】
#include <stdio.h>/*printf()を使うので必要*/
void sub(void)
{
printf("Hello world\n");
}

main.cで「printfを使うsub()を呼ぶから、main.cでも#include <stdio.h>が必要」とは思わないですよね。

「main.cはsub()を呼ぶだけだから、sub()の宣言だけする。sub()の中で何を呼ぼうが、そんな事は知ったこっちゃない」ので、main.cでは「一切、何のヘッダーもインクルードする必要はない」のです。

exeからDLLを呼ぶ時も同様で「exeはDLLの入り口さえ知ってれば良い」ので「DLLの中で何を使われていようが知ったこっちゃない」でOKなのです。

「関数を呼んだら、呼んだ先の事は知らない」のがCやC++の良い所でもあり、悪い所でもあります。

以下のような「単純な例」で考えれば「インクルードは不要」だと判るでしょう。

【main.c】
void sub(void);/*sub()が何者なのかを宣言しておく*/
int main(void)
{
sub();
}

【sub.c】
#include <stdio.h>/*printf()を使うので必要*/
void sub(void)
{
printf("Hello world\n");
}

main.cで「printfを使うsub()を呼ぶから、main.cでも#include <stdio.h>が必要」とは思わないですよね。

...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報