主な違いは、静的にリンクされたライブラリをアプリに含めることです。これらは、アプリをビルドするときにリンクされます。動的ライブラリは実行時にリンクされるため、アプリに含める必要はありません。最近では、動的ライブラリを使用して、すべてのコンピューターに多数の動的ライブラリを配置することでアプリのサイズを縮小しています。
動的ライブラリを使用すると、ユーザーはクライアント アプリを再構築せずにライブラリを更新することもできます。アプリで使用するライブラリにバグが見つかり、それが静的にリンクされている場合は、アプリを再構築してすべてのユーザーに再発行する必要があります。動的にリンクされたライブラリにバグが見つかった場合、すべてのユーザーはライブラリを更新するだけでよく、アプリを更新する必要はありません。
<ブロック引用>
C++ プログラムがコンパイルされるとき。 C++ ライブラリの関数とコード (ライブラリのコードなど) への参照が必要です。
libdyno.so
という架空の共有ライブラリがあるとします。 .最終的に objdump
を使用して内部を覗くことができます または nm
.
objdump --syms libdyno.so
共有ライブラリを使用して、システムで今日これを行うことができます。 objdump
MAC では gobjdump
と呼ばれます binutils
で brew が付属しています パッケージ。これを Mac で試してみてください...
gobjdump --syms /usr/lib/libz.dylib
シンボルが共有オブジェクトに含まれていることがわかります。 link
の場合 共有オブジェクトでは、通常、次のようなものを使用します
g++ -Wall -g -pedantic -ldyno DynoLib_main.cpp -o dyno_main
-ldyno
に注意してください そのコマンドで。これは、コンパイラ (実際にはリンカー ld) に libdyno.so
という共有オブジェクト ファイルを探すように指示しています。 通常それらを探す場所。そのオブジェクトが見つかると、必要なシンボルを見つけることができます。開発者が -l
を指定して動的ライブラリをロードするように要求したため、循環依存関係はありません
動的ライブラリをいつ、どのように使用しますか?どうやって作るの?標準の .cpp ファイルからそのようなファイルを生成するために使用される特定のコンパイル コマンドは何ですか
DynoLib.cpp という名前のファイルを作成します
#include "DynoLib.h"
DynamicLib::DynamicLib() {}
int DynamicLib::square(int a) {
return a * a;
}
DynoLib.h という名前のファイルを作成します
#ifndef DYNOLIB_H
#define DYNOLIB_H
class DynamicLib {
public:
DynamicLib();
int square(int a);
};
#endif
以下のようにコンパイルして共有ライブラリにします。これは Linux 固有のものです...
g++ -Wall -g -pedantic -shared -std=c++11 DynoLib.cpp -o libdyno.so
以前に与えたコマンドを使用して、このオブジェクトを調べることができます。
objdump --syms libdyno.so
libdyno.so
にリンクする DynoLib_main.cpp というファイルを作成します。 定義したばかりの関数を使用します。
#include "DynoLib.h"
#include <iostream>
using namespace std;
int main(void) {
DynamicLib *lib = new DynamicLib();
std::cout << "Square " << lib->square(1729) << std::endl;
return 1;
}
次のようにコンパイルします
g++ -Wall -g -pedantic -L. -ldyno DynoLib_main.cpp -o dyno_main
./dyno_main
Square 2989441
nm
を使用してメイン バイナリを確認することもできます。 .以下では、文字列 square
を持つものがあるかどうかを確認しています その中に、つまり libdyno.so
から必要なシンボルがあります 私のバイナリで何らかの方法で参照されています。
nm dyno_runner |grep square
U _ZN10DynamicLib6squareEi
答えはイエスです。大文字の U
は未定義を意味しますが、これは以前に作成した DynamicLib クラスの square メソッドのシンボル名です。奇妙に見える名前は、独自のトピックである名前マングリングによるものです。
通常の.o ファイルの場合と同じように静的にリンクするファイルと、動的にリンクする必要があるファイルをどのように確認できますか?
知る必要はありません。リンクしたいものを指定し、コンパイラー (およびリンカーなど) に作業を任せます。 -l
に注意してください フラグはライブラリと -L
に名前を付けます どこを見るかを指示します。コンパイラがここで物事を見つける方法についてのまともな記事があります
gcc リンケージ オプション -L:動的ライブラリへのパスを指定する別の方法
または man ld
を見てください .
-L フラグと -l フラグは何のためのものですか?たとえば、コマンド ラインで -lusb フラグを指定するとはどういう意味ですか?
上記のリンクを参照してください。これは man ld
からです ..
-L searchdir
ld がアーカイブ ライブラリと ld 制御スクリプトを検索するパスのリストにパス searchdir を追加します。このオプションは何度でも使用できます。ディレクトリは、コマンド ラインで指定された順序で検索されます。コマンド ラインで指定されたディレクトリは、デフォルト ディレクトリの前に検索されます。オプションが表示される順序に関係なく、すべての -L オプションがすべての -l オプションに適用されます。 -L オプションは、-T オプションが指定されていない限り、ld がリンカースクリプトを検索する方法に影響しません。`
ここにたどり着いた場合は、リンカー、つまり ld について学ぶことで利益が得られます。これは重要な役割を果たしており、多くの混乱の原因となっています。なぜなら、ほとんどの人はコンパイラを扱い始めて compiler == linker
と考えるからです。 これは正しくありません。