パッケージ(Delphi)
ライブラリとパッケージ:インデックス への移動
単純な手続きや関数以外のものをエクスポートする方法としては、通常、パッケージが望ましいでしょう。 ライブラリを検討しなければならないのは、他のプログラムとの相互運用性が要件の 1 つになる場合だけです。
以下のトピックでは、パッケージおよびパッケージの作成とコンパイルにかかわるさまざまな問題について説明します。
- パッケージ宣言とソース ファイル
- パッケージの命名
- requires 句
- パッケージの循環参照の回避
- パッケージの重複参照
- contains 句
- ソース コードの冗長な使用の回避
- パッケージのコンパイル
- 生成されるファイル
- パッケージ固有のコンパイラ指令
- パッケージ固有のコマンドライン コンパイラ スイッチ
目次
パッケージの概要
パッケージは、アプリケーション、IDE、あるいはその両方で使用される特別にコンパイルされたライブラリです。 パッケージを用いると、ソース コードに影響を与えずに、コードの場所を変えることができます。 これは、アプリケーション パーティショニングと呼ばれることもあります。
実行時パッケージは、ユーザーがアプリケーションを実行する際に機能を提供します。 設計時パッケージは、IDE にコンポーネントをインストールしたり、カスタム コンポーネント用の特別なプロパティ エディタを作成するために使用されます。 パッケージは 1 つで設計時にも実行時にも機能でき、設計時パッケージは多くの場合 requires 句で実行時パッケージを参照することで機能します。
Win32 では、拡張子 .bpl(Borland パッケージ ライブラリ)がパッケージ ファイルの末尾に付きます。
パッケージは通常、アプリケーションの起動時に静的に読み込まれます。 ただし、(SysUtils ユニットの)LoadPackage ルーチンと UnloadPackage ルーチンを使用すれば、パッケージを動的に読み込めます。
メモ: それでも、アプリケーションでパッケージを利用する場合は、パッケージ化された各ユニットの名前がそのユニットを参照するあらゆるソース ファイルの uses 句に明示される必要があります。
パッケージ宣言とソース ファイル
各パッケージは個別のソース ファイルで宣言されます。パッケージは、Delphi コードが記述された他のファイルとの混同を避けるために、.dpk 拡張子を付けて保存されなければなりません。 パッケージ ソース ファイルには、型、データ、手続き、関数の宣言は含まれていません。 代わりに、以下のものが含まれています。
- パッケージの名前。
- 新しいパッケージで必要な他のパッケージのリスト。 これらは、新しいパッケージのリンク先パッケージになります。
- コンパイル時にパッケージにまとめられるユニット ファイルのリスト。 これらのソースコード ユニットはコンパイル済みパッケージの機能を提供するものであり、パッケージは実質的にはそれらのユニットのラッパーです。
パッケージ宣言の形式は以下のとおりです。
package packageName; requiresClause; containsClause; end.
ここで、packageName は任意の有効な識別子です。 requiresClause と containsClause はどちらも省略可能です。 たとえば、次のコードでは DATAX パッケージを宣言しています。
package DATAX;
requires
rtl,
contains Db, DBLocal, DBXpress, ... ;
end.
requires 句には、宣言対象のパッケージで使用される他の外部パッケージが列挙されます。 この句は requires 指令で始まり、その後にパッケージ名のコンマ区切りリストが続き、最後にセミコロンが付きます。 パッケージが他のパッケージを参照しない場合、requires 句は不要です。
contains 句は、コンパイルしてパッケージにまとめるユニット ファイルを指定します。 この句は contains 指令で始まり、その後にユニット名のコンマ区切りリストが続き、最後にセミコロンが付きます。 ユニット名の後には、予約語 in と、単一引用符で囲んだソース ファイル名(ディレクトリ パスは省略可能)を指定できます。ディレクトリ パスは絶対パスでも相対パスでもかまいません。 例:
contains MyUnit in 'C:\MyProject\MyUnit.pas';
メモ: パッケージ化されたユニット内のスレッドローカル変数(threadvar で宣言されているもの)には、そのパッケージを使用するクライアントからはアクセスできません。
パッケージの命名
コンパイル済みのパッケージには、生成されるいくつかのファイルが関係してきます。 たとえば、DATAX というパッケージのソース ファイルは DATAX.DPK で、そこからコンパイラにより以下の実行可能ファイルとバイナリ イメージが生成されます。
DATAX.BPL および DATAX.DCP
DATAX は、パッケージを他のパッケージの requires 句で参照する場合や、パッケージをアプリケーションで利用する場合に使用されます。 パッケージ名はプロジェクト内で一意でなければなりません。
requires 句
requires 句には、現在のパッケージで使用される他の外部パッケージが列挙されます。 これは、ユニット ファイル内の uses 句と同じように機能します。 requires 句で指定された外部パッケージは、その外部パッケージに含まれているいずれかのユニットと現在のパッケージを両方とも使用するアプリケーションに、コンパイル時に自動的にリンクされます。
パッケージに含まれているユニット ファイルが他のパッケージ内ユニットを参照する場合、後者のパッケージは前者のパッケージの requires 句に含まれていなければなりません。 他のパッケージが requires 句から省略された場合、コンパイラは参照先ユニットを .dcu ファイルから読み込みます。
パッケージの循環参照の回避
パッケージの requires 句には循環参照を含むことはできません。 つまり、
- パッケージは自分の requires 句で自分自身を参照することはできません。
- 参照チェーンは、チェーン内のどのパッケージも再参照せずに終了しなければなりません。 たとえば、パッケージ A にパッケージ B が必要な場合、パッケージ B にはパッケージ A が必要であってはならず、パッケージ A にパッケージ B が必要で、パッケージ B にパッケージ C が必要な場合、パッケージ C にはパッケージ A が必要であってはなりません。
パッケージの重複参照
コンパイラでは、パッケージの requires 句に含まれている重複参照を無視します。 しかし、プログラムが明快で読みやすくなるように、重複参照は削除しなければなりません。
contains 句
contains 句は、パッケージにまとめるユニット ファイルを指定します。 contains 句ではファイル名拡張子を付けないでください。
ソース コードの冗長な使用の回避
パッケージは、別のパッケージの contains 句や、ユニットの uses 句で指定することはできません。
パッケージの contains 句に直接含まれるユニットや、それらのユニットの uses 句に間接的に含まれるユニットはすべて、コンパイル時にパッケージにまとめられます。 パッケージに(直接または間接に)含まれているユニットは、そのパッケージの requires 句で参照されている他のいかなるパッケージにも含めることはできません。
同じアプリケーションで使用する複数のパッケージに、同じユニットを(直接または間接に)含めることはできません。
パッケージのコンパイル
パッケージは、通常、[プロジェクト マネージャ] で生成された .dpk ファイルを使って IDE からコンパイルされます。 また、コマンドラインから直接 .dpk ファイルをコンパイルすることもできます。 パッケージを含んだプロジェクトをビルドすると、そのパッケージは必要に応じて暗黙に再コンパイルされます。
生成されるファイル
パッケージが正常にコンパイルされたときに生成されるファイルの一覧を以下の表に示します。
コンパイル済みパッケージ ファイル
ファイル拡張子 | 内容 |
---|---|
DCP |
パッケージ ヘッダーおよびパッケージ内のすべての .dcu(Win32)ファイルを連結したもので構成されるバイナリ イメージ。 各パッケージごとに、.dcp または .dcp ファイルが 1 つだけ生成されます。 .dpk ソース ファイルの基本名がこのファイルの基本名になります。 |
BPL |
実行時パッケージ。 このファイルは、RAD Studio 固有の特別な機能を備えた Win32 版 DLL です。 dpk ソース ファイルの基本名がパッケージの基本名になります。 |
パッケージ固有のコンパイラ指令
ソース コードに挿入できるパッケージ固有のコンパイラ指令の一覧を以下の表に示します。
パッケージ固有のコンパイラ指令
指令 | 用途 |
---|---|
{$IMPLICITBUILD OFF} |
パッケージが後で暗黙に再コンパイルされないようにします。 低レベル機能を提供するパッケージ、ビルド間でほとんど変わらないパッケージ、ソース コードが配布されないパッケージをコンパイルする際に .dpk ファイルで使用します。 |
{$G-} または {$IMPORTEDDATA OFF} |
インポートされたデータの参照が作成されないようにします。 この指令を使用すると、メモリアクセス効率は向上しますが、ユニットでは他のパッケージ内の変数を参照できなくなります。 |
{$WEAKPACKAGEUNIT ON} |
ユニットを弱くパッケージ化します。 |
{$DENYPACKAGEUNIT ON} |
ユニットがパッケージに格納されないようにします。 |
{$DESIGNONLY ON} |
パッケージを IDE へのインストール用にコンパイルします (Put in .dpk file.) |
{$RUNONLY ON} |
パッケージを実行時専用としてコンパイルします。 (Put in .dpk file.) |
ソース コードに {$DENYPACKAGEUNIT ON} を挿入すると、ユニット ファイルはパッケージ化されなくなります。 {$G-} または {$IMPORTEDDATA OFF} を挿入すると、パッケージが同じアプリケーションで他のパッケージと一緒に使用されるのを防ぐことができます。
パッケージ ソース コードには、適宜、他のコンパイラ指令も含めることができます。
パッケージ固有のコマンドライン コンパイラ スイッチ
コマンドライン コンパイラで使用可能なパッケージ固有のスイッチは以下のとおりです。
パッケージ固有のコマンドライン コンパイラ スイッチ
スイッチ | 用途 |
---|---|
-$G- |
インポートされたデータの参照が作成されないようにします。 このスイッチを使用すると、メモリアクセス効率は向上しますが、コンパイルしたパッケージでは他のパッケージ内の変数を参照できなくなります。 |
-LEpath |
コンパイル済みパッケージ ファイルが格納されるディレクトリを指定します。 |
-LNpath |
パッケージの dcp または dcp ファイルが格納されるディレクトリを指定します。 |
-LUpackageName[;packageName2;...] |
アプリケーションで使用する追加の実行時パッケージを指定します。 プロジェクトのコンパイル時に使用されます。 |
-Z |
パッケージが後で暗黙に再コンパイルされないようにします。 低レベル機能を提供するパッケージ、ビルド間でほとんど変わらないパッケージ、ソースコードが配布されないパッケージをコンパイルする際に使用します。 |
-$G- スイッチを使用すると、パッケージが同じアプリケーションで他のパッケージと一緒に使用されるのを防ぐことができます。
パッケージのコンパイル時には、適宜、他のコマンドライン オプションも使用できます。