#pragma package

提供: Appmethod Topics
移動先: 案内検索

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 指令が再定義された" というコンパイラ エラーが発生するおそれがあります。

このプラグマは、コンパイル ユニットの初期化順序に影響を及します。ユニットの場合、初期化は以下の順に行われます。

  1. "uses" 句に基づく依存関係による順序(つまり、unitA が unitB に依存する場合、unitB は unitA より先に初期化される必要があります)
  2. リンク順序
  3. ユニット内の優先順序

通常のオブジェクト ファイル(ユニットとしてビルドされないもの)の場合、初期化は優先順序に従ってまず行われ、次にリンク順序に従って行われます。オブジェクト ファイルのリンク順序を変更すると、グローバル オブジェクト コンストラクタが呼び出される順序が変わります。

以下の例では、ユニットと通常のオブジェクト ファイルで初期化がどう異なるかを示しています。

#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) 指令が含まれたユニット ファイルには、グローバル変数を定義しないでください。

弱いパッケージの使用の詳細については、「弱いパッケージ」を参照してください。

関連項目