標準/拡張機能 | C/C++ | 依存項目 |
---|---|---|
Language Environment | C のみ |
#include <stdlib.h>
void ( *fetchep( void ( *entry_point)()))();
共用書き込み可能静的変数を使用して一連の関数を動的にフェッチ します。fetchep() は、エントリー・ポイントを登録するために使用します。フェッチ境界をまたいで受け渡され、オリジナルのエントリー・ポイントであ るかのように使用される、ポインターを戻します。したがって、フェッチされたモジュールから複数のエントリー・ポイントを作 成できます。新しいエントリー・ポイントへの呼び出しでは、呼び出しごとにオリジナルのフェッ チ・ポインターが使用されるように、同じ書き込み可能静的変数を使用します。
fetchep() は、フェッチされたモジュール内で呼び出されます が、fetch() 呼び出しと同じレベルからは呼び出されません。フェッチされたモジュールではないルート・プログラム内で fetchep() が 呼び出された場合、fetchep() は、そのルート・プログラムの 書き込み可能静的変数 (存在する場合) を使用するフェッチ・ポインターを 戻します。
fetchep() への入力として指定した entry_point が、現行モジュールにとって外部の関数アドレスである場合、または無効な 関数アドレスである場合は、その呼び出しから戻されたポインターを使用する と、未定義の動作が生じる結果となります。
#pragma linkage(entry_point, FETCHABLE)
さらに、再入可能なモジュールをフェッチするステップは、fetch() - ロード・モジュールの取得の記述のとおりに従わなければなりません。書き込み可能静的変数が不要 な場合、fetchep() を使用する C モジュールにディレクティブ #pragma linkage(…, FETCHABLE) を含める必要はありません。
オリジナル・フェッチ・ポインター、またはそれから作成された別のフェッ チ・ポインターで、新しいフェッチ・ポインターを他に影響を与えることなく 解放することができます。ただし、フェッチされたオリジナルの関数が解放される と、fetchep() 関数を使用して作成されたすべてのフェッチ・ポインターも 解放されます。解放された時点のフェッチ・ポインターや、オリジナルが解放された時点のフェッチ・ポインターを使用しようとすると、未定義の動作を引き起こすことになります。
ユーザーのネーム・スペースが侵害されるのを回避するため、この非標準関数には 2 つの名前があります。外部エントリー・ポイント名である一方の名前には、接頭部として 2 つの 下線文字が付いていて、もう一方の名前には付いていません。接頭部下線文字が付いていない名前は、LANGLVL(EXTENDED) を使用する場合にのみ表示されます。
この関数を使用するには、その外部エントリー・ポイント名を使用する 関数 (すなわち、2 つの下線文字で始まる名前、__ftchep()) を呼び出すか、LANGLVL(EXTENDED) を使用してコンパイルする必要があります。LANGLVL(EXTENDED) を使用すると、ヘッダー内の関連情報も表示されます。
/* The module that calls fetch() */
#include <stdlib.h>
typedef int (*FUNC_T)();
int main(void) {
FUNC_T (*myfunc)();
FUNC_T myfunc1;
FUNC_T myfunc2;
FUNC_T myfunc3;
myfunc = (FUNC_T (*)())fetch("MYMOD");
myfunc1 = myfunc(0);
myfunc2 = myfunc(1);
myfunc3 = myfunc(2);
}
/*
The following code is the fetched module.
Please see fetch() for information on how to compile and link the
above.
*/
/* inside MYMOD */
#include <stdlib.h>
typedef int (*FUNC_T)();
int k; /* global variable to share within MYMOD */
#pragma linkage(x, fetchable)
FUNC_T x(int a)
{
switch(a)
{
case 0:
return (FUNC_T)fetchep((void(*)())func1);
case 1:
return (FUNC_T)fetchep((void(*)())func2);
case 2:
return (FUNC_T)fetchep((void(*)())func3);
}
{
int func1(int a, int b)
{
k = 6;
⋮
}
int func2(int a, int b)
{
k = 4;
⋮
}
int func3(int a, int b)
{
k = 5;
⋮
}