#pragma package
Pragma 指令の概要:インデックス への移動
目次
構文(「疑似文法」を参照)
#pragma package(smart_init) #pragma package(smart_init, weak)
説明
#pragma package(smart_init)
#pragma package(smart_init)
を指定すると、パッケージ化されたユニットは必ずそれらの依存関係(パッケージ ソース ファイルにデフォルトで含まれている)で決まる順序で初期化されることになります。通常は、パッケージとしてビルドされる .cpp ファイルに #pragma package
を使用することになるでしょう。
- メモ: ヘッダー ファイルでは
#pragma package(smart_init)
を使用しないでください。使用した場合は、"E2177 異なる値で #pragma package 指令が再定義された" というコンパイラ エラーが発生するおそれがあります。
このプラグマは、コンパイル ユニットの初期化順序に影響を及します。ユニットの場合、初期化は以下の順に行われます。
- "uses" 句に基づく依存関係による順序(つまり、unitA が unitB に依存する場合、unitB は unitA より先に初期化される必要があります)
- リンク順序
- ユニット内の優先順序
通常のオブジェクト ファイル(ユニットとしてビルドされないもの)の場合、初期化は優先順序に従ってまず行われ、次にリンク順序に従って行われます。オブジェクト ファイルのリンク順序を変更すると、グローバル オブジェクト コンストラクタが呼び出される順序が変わります。
以下の例では、ユニットと通常のオブジェクト ファイルで初期化がどう異なるかを示しています。
例
#pragma package(smart_init)
で "スマート初期化" されている A、B、C という 3 つのソース ファイルがあり、そのそれぞれに、(#pragma startup
の優先度パラメータで定義される)優先度値が 10、20、30 に設定された関数があるとしましょう。これらの関数は、優先度値と定義元のソース ファイルに従って名前が付けられています。そのため、関数名は a10、a20、a30、b10、b20 などとなります。
これら 3 つのプログラム A、B、C は以下のとおりです。
// A.cpp
#include <stdio.h>
#ifdef USE_PACKAGE_INIT
#pragma package(smart_init)
#endif
void A10() {
printf("%s() ", __FUNCTION__);
}
#pragma startup A10 10
void A20() {
printf("%s() ", __FUNCTION__);
}
#pragma startup A20 20
void A30() {
printf("%s() ", __FUNCTION__);
}
#pragma startup A30 30
// B.cpp
#include <stdio.h>
#ifdef USE_PACKAGE_INIT
#pragma package(smart_init)
#endif
void B10() {
printf("%s() ", __FUNCTION__);
}
#pragma startup B10 10
void B20() {
printf("%s() ", __FUNCTION__);
}
#pragma startup B20 20
void B30() {
printf("%s() ", __FUNCTION__);
}
#pragma startup B30 30
// C.cpp
#include <stdio.h>
#ifdef USE_PACKAGE_INIT
#pragma package(smart_init)
#endif
void C10() {
printf("%s() ", __FUNCTION__);
}
#pragma startup C10 10
void C20() {
printf("%s() ", __FUNCTION__);
}
#pragma startup C20 20
void C30() {
printf("%s() ", __FUNCTION__);
}
#pragma startup C30 30
USE_PACKAGE_INIT を定義したうえで上記のソース ファイルをビルドした場合は、プログラムを実行すると、以下が出力されます。
A10() A20() A30() B10() B20() B30() C10() C20() C30()
つまり、優先度は無視され、各ユニットではその初期化がすべて同時に実行されます。
USE_PACKAGE_INIT を定義せずにこれらのソース ファイルをビルドした場合は、まったく異なる結果になります。この場合、プログラムを実行すると、以下が出力されます。
A10() B10() C10() A20() B20() C20() A30() B30() C30()
つまり、#pragma startup の優先度が使用されます。
これら 3 つはすべてユニットであるため、A で B と C を使用していて、リンク順序が A、B、C の場合、初期化順序は B10() B20() B30() C10() C20() C30() A10() A20() A30()
になります。
上記がユニットではなくオブジェクト ファイルであった場合、順序は A10() B10() C10() A20() B20() C20() A30() B30() C30()
になります。
#pragma package(smart_init)
を使用している .cpp ファイルの場合はまた、#pragma package(smart_init)
を宣言している .cpp ファイルから他のオブジェクト ファイルへの #pragma link
参照がすべてユニットで解決される必要があります。オブジェクト ファイル以外への #pragma link
参照は、まだライブラリなどで解決できます。
#pragma package(smart_init, weak)
#pragma package(smart_init, weak)
指令は、パッケージの .bpi ファイルおよび .bpl ファイルへのオブジェクト ファイルの格納方法に影響を及します #pragma package(smart_init, weak)
がユニット ファイルで検出された場合、コンパイラはそのユニットを BPL からできるだけ除外し、別のアプリケーションやパッケージで必要になったときには、そのユニットの非パッケージ化ローカル コピーを作成します。この指令を付けてコンパイルされたユニットは "弱くパッケージ化されている" と言われます。
#pragma package(smart_init, weak)
は、同じ外部ライブラリに依存している可能性のあるパッケージ間の競合を解消するために使用されます。
#pragma package(smart_init, weak)
指令が含まれたユニット ファイルには、グローバル変数を定義しないでください。
弱いパッケージの使用の詳細については、「弱いパッケージ」を参照してください。