Lazarus/FPC Libraries/ja
│
English (en) │
español (es) │
français (fr) │
日本語 (ja) │
русский (ru) │
このページでは Lazarus/FPC でライブラリを作成しうる方法やプロジェクト、パッケージでそれらを利用する方法を述べます。
関連項目
- Creating bindings for C libraries/ja - C のヘッダファイル (.h) を Pascal のユニットに変換する方法。
総論
静的ライブラリ: デフォルトでは FPC は静的リンクを用いて実行ファイルをコンパイル・リンクします。即ち、リンカはプロジェクトと各パッケージに含まれる全ての .o ファイルをまとめて一つの大きな実行ファイルにします。利点は外部環境への依存性がないことで、欠点は一台のコンピュータにある複数のプログラムがコードを共有できないことです。また、プラグインをロード/アンロードすることもできません。
動的ライブラリ(ダイナミック・ライブラリ): 動的ライブラリの考え方は、ライブラリをプログラム間で共有することで、コードを格納するメモリ領域を節約し、頻繁に利用されるライブラリでは軌道時間を短縮し、プラグインを可能にしようという発想です。動的ライブラリの欠点は、たまにしか利用されないライブラリでは遅くなること、内部構造が複雑になること(これは主にコンパイラ側の課題です)、初期化の方法が異なること(後述)、互換性のある共有コードだけを混用するための version system が必要になることです。
オペレーティング・システム
動的ライブラリ:
オペレーティング・システム | 動的ライブラリ | 静的ライブラリ |
---|---|---|
FreeBSD | .so | .a |
macOS | .dylib | .a |
Linux | .so | .a |
Windows | .dll | .lib |
Haiku | .so | .a |
FreeBSD
macOS
Linux
動的ライブラリのファイル名は常に 'lib'+パッケージ名+'.so'+ヴァージョン という形をとります。例えば: libz.so.1 や libz.so.1.2.2。
Linux は環境変数 LD_LIBRARY_PATH に従ってライブラリを検索し、次いで /lib、次いで /usr/lib、最後に /etc/ld.so.conf を見ます。
Linux 環境下で(FPC で書かれたものではない)他のライブラリとメモリを共有するには(GetMem / FreeMem、string型)、unit cmem を用いる必要があります。メモリ割当を行う他のユニットより先にこのユニットの初期化部が呼び出されるように、このユニットは、プロジェクトの主ソースファイル(典型的には .lpr)の uses 節の先頭におくようにします。
Windows
Windows はカレントディレクトリ、システムディレクトリ、環境変数 PATH で指定されたディレクトリを検索します。
ppumove, .ppu, .ppl
通常の場合、FPC はユニット毎に .ppu ファイルと .o ファイルを一つづつ生成します。.ppu ファイルは .pas/.pp ファイルの重要な情報(型、.o ファイルなどの必要なファイル名)を全て含んでおり、一方 .o ファイルはアセンブラ・コードと現用のシステム向けに名前修飾された識別子を含んでいます。
ツール ppumove は全ての FPC インストールパッケージに含まれており、一つまたは複数の .ppu ないし .o ファイルを単一の動的ライブラリに変換します。この機能ははリンカを呼び出すことで行われます。リンカは全ての .o ファイルを集めて一つの .so ファイル(Windows では .dll、Mac OS X では .dylib)にし、.o ファイルへの参照を .ppu ファイルから取り除きます。このようにして作られた新しい .ppu ファイルは普通 .pplファイル と呼ばれます。
例:
パッケージの出力ディレクトリ(.ppu ファイルがある)で、
ppumove -o packagename -e ppl *.ppu
とすると、全ての .ppu ファイルが .ppl ファイルに変換され、一つのファイルlibpackagename.so (Windowsでは: packagename.dll)が生成されます。Linux では、ライブラリファイルの名前の先頭には必ず 'lib' が付けられることを知っておいてください。
こうして生成された新しいライブラリはそのまま C などの他のプログラミング言語から利用することができます。FPC のプログラムからも external 修飾子を付ければ利用することができます。しかし、初期化/終了 initialization/finalization セクションが自動的に呼び出されなければなりません。その過程でヒープマネジャの初期化と終了処理が行われるからです。さもないと string型変数も GetMem も使えません。この点 FPC プログラマは甘やかされており(訳注: 何もしないでも初期化/終了処理が自動実行されるから)、もっといい目にあっているわけです。
dlopen -動的ライブラリのロード
動的ライブラリのロードは、dl ユニットの中の dlopen 関数を利用すると簡単にできます。
ToDo: 誰か例を付け加えてください
主な問題は、ファイル名の取得です。ファイル名はヴァージョンとOSに依存します。
初期化処理
それぞれのユニットに、初期化 initialization セクションを一つ含めることができます。初期化セクションが実行される順序は、uses 節でのユニット記述順に従います。
How to initialize a dynamic library: ToDo
終了処理
それぞれのユニットに、終了 finalization セクションを一つ含めることができます。終了セクションが実行される順序は、初期化セクションが実行される順序の逆です。
ヴァージョン、配布
ライブラリは時の経過とともに育ち、変わっていくものです。新しい機能を付け加えるのは問題がありませんが、パブリックメソッドを削除したり、引数を変更したりすると、ライブラリの互換性が失われます。そうなると、インストール済のライブラリ (.so, .dll, .dylib) を互換性のあるものと置き換えたり、あるいは新たなライブラリをシステムに追加したりしないとなりません。これが全てのライブラリにヴァージョン番号が必要な理由です。
dl ユニットの中の dlopen 関数を用いて動的ライブラリをロードするためには正確なファイル名がわかっていないとなりません。Linux 環境下では、ヴァージョン番号がわかっている必要があるわけです。
ToDo: proposal how the IDE should create version numbers