fetch() - ロード・モジュールの取得

標準

標準/拡張機能 C/C++ 依存項目
Language Environment C  

形式

#include <stdlib.h>

void (*fetch(const char *name))();

機能説明

name で指定されたロード・モジュールをメモリーへ動的にロードします。その後は、z/OS® XL C プログラムから そのロード・モジュールを呼び出すことができます。フェッチ可能なロード・モジュールをロード・モジュール・ライブラリー 内で識別するための名前または別名を、fetch() ライブラリー関数呼び出し の中に指定する必要があります。

ユーザーのネーム・スペースが侵害されるのを回避するため、この非標準関数には 2 つの名前があります。外部エントリー・ポイント名である一方の名前には、接頭部として 2 つの 下線文字が付いていて、もう一方の名前には付いていません。接頭部下線文字が付いていない名前は、LANGLVL(EXTENDED) を使用する場合にのみ表示されます。

この関数を使用するには、その外部エントリー・ポイント名 を使用する関数 (つまり、2 つの下線文字で始まる名前) を 呼び出すか、または LANGLVL(EXTENDED) でコンパイルする必要があります。LANGLVL(EXTENDED) を使用すると、ヘッダー内の関連情報もすべて表示されます。

main() が含まれているモジュールをフェッチすることはできません。それをフェッチした場合、fetch() は、使用できないポインターを 戻します。そのポインターを使用すると、未定義の動作を行う結果となります。このような種類のモジュールを呼び出すには、system() ライブラリー 関数を使用してください。代わりに、モジュールの作成時に、リンケージが z/OS XL C で提供されるようにエントリー・ポイントをリセットすることもできます。

再入不能なモジュールが複数回フェッチされた場合は、逆順にそれらを解放しなければなりません。そうでない場合は、ロード・モジュールはすぐに削除されます。

C および C++ で作成 されたモジュールをフェッチすることができます。C モジュールでは、フェッチされるモジュールのソースは、一般に、#pragma linkage(…, fetchable) を含みます (例外は以下で説明します)。C++ モジュールをフェッチ するためには、そのルーチンを extern “C” であると宣言する必要 があり、また、#pragma linkage(…, fetchable) ディレクティブ で宣言する必要があります。#pragma linkage に必要な情報については、fetchep() - 書き込み可能静的変数の共用も参照してください。

注: C または C++ モジュールで、XPLINK オプションでコンパイルされていて、フェッチされる場合、#pragma linkage(..., fetchable) が必要です。それらのモジュールは、エントリー・ポイントをリセットする技法を使用することはできません。アプリケーションが、FETCHABLE を指定しなかった XPLINK ルーチンに対して fetch() を試みると、エラーが戻されます。

XPLINK プログラムは、非 XPLINK プログラムをフェッチすることができ、その逆も可能です。fetch() によって戻された関数記述子には、必要に応じて、スタック・スワップおよびパラメーター・リストの型変換をサポートするグルー・コードが含まれます。XPLINK リンケージ境界を横断しないフェッチ・ルーチンへの呼び出しでは、グルー・コードのオーバーヘッドは発生しません。

フェッチされたモジュールが DLL としてコンパイルされる場合は、別の DLL モジュールから変数や関数をインポートすることができますが、変数や関数を エクスポートすることはできません。

ネストされたフェッチはサポートされています。つまり、フェッチされたモジュールは、fetch() ライブラリー関数を 呼び出して、フェッチ可能な別のモジュールを動的にロードすることも できます。

多重フェッチもサポートされています。モジュールの複数回のフェッチの結果、個々のフェッチ・ポインターを作成します。モジュールが「再入可能」のマークが付けられている場合は、多重フェッチでは、モジュールをストレージに再ロードしません。 MVS™ では、ロードの時間を節約するために、再入可能モジュールを、拡張リンク・パック域またはリンク・パック域 (ELPA/LPA) に置くことができます。再入可能なモジュールの複数コピーはストレージに入れられませんが、フェッチごとに、別のポインターを戻します。モジュールが再入可能でない場合、多重フェッチでは、ストレージへの複数回のロードが行われます。再入不能モジュールを複数回 fetch() した場合、すべての フェッチ・インスタンスが解放された後でなければ、release() によって そのモジュールが削除されないことがあるので、注意してください。また、再入不能なモジュールの複数回のロードは、ストレージの点で非常にコ ストがかかることを覚えておいてください。

書き込み可能静的変数は、一般にプロセスの範囲内で有効です。例外は、スレッドがフェッチされたモジュールを呼び出すとき、書き込み可能静的変数はそのスレッドに対してのみ変更されます。つまり、スレッドの範囲でのみ有効です。

MVS では、フェッチ可能 (または動的にロードされる) モジュールは、リンク・エディットされ、標準システム検索を使用してアクセス 可能でなければなりません。MVS は再入不能、逐次再使用可能、および再入可能のモジュールの取り出しをサポートしています。

しかし POSIX では、フェッチ可能で、動的にロードされたモジュールは HFS (階層ファイル・システム) には入れられません。 また、POSIX および XPG4 外部変数は伝搬されることにも注意してください。外部変数についての詳細は、「z/OS XL C/C++ プログラミング・ガイド」を参照してください。

ユーザーのプログラムが本来再入可能であれば、各再入可能モジュールは 、書き込み可能静的変数の別々のコピーを持ちます。以下のステップに従って、書き込み可能静的変数を持つ再入可能モジュールを フェッチすることができます。

  1. RENT コンパイル時オプションを使用して、フェッチ されるモジュールをコンパイルする。
  2. ステップ 1 で作成されるオブジェクト・モジュールを使用して、フェッチ可能なメンバーを生成する。 #pragma linkage(…, FETCHABLE) ディレクティブを組み込まなければ、取り出し中の関数としてエントリー・ポイントを指定 しなければなりません。
フェッチ可能モジュールのプログラム・フローについては、図 1 を参照してください(FECB はフェッチ制御ブロックを意味します。これは、fetch() によって使用される z/OS XL C 内部制御ブロックです)。
図 1. フェッチ可能モジュールのプログラム・フロー
フェッチ可能モジュールのプログラム・フロー

共用書き込み可能静的変数を使用して一連の関数を動的にフェッチする ためには、ライブラリー関数の fetchep() を使用できます。詳しくは、fetchep() - 書き込み可能静的変数の共用を参照してください。

フェッチされるモジュールと fetch() ライブラリー関数を呼び出す モジュールの両方が再入可能になることができます。

フェッチされるモジュールで、#pragma linkage(…, FETCHABLE) ディレクティブを 指定しないでモジュールをフェッチすることができます。その場合、フェッチ・ポインターを使用すると、そのモジュールのエントリー・ポ イントを呼び出す結果となります。モジュールをリンクするとき、エントリー・ポイントをリセットしなければな りません。さらに、書き込み可能静的変数を一切持つことはできません。

また、書き込み可能静的変数を含む再入可能 C モジュールをフェッチするには、フェッチされるモジュールで #pragma linkage(… FETCHABLE) プリプロセッサー指示を使用する必要があります。

エントリー・ポイント・リンケージが C リンケージでない場合は、typedef で定義された関数ポインターと一緒に pragma linkage を使用しなければなりません。以下のサンプルの抜粋では、COBOL ルーチンに COBOL リンケージを設定します。
typedef int COBOL_FUNC ();
#pragma linkage (COBOL_FUNC, COBOL)
⋮
COBOL_FUNC * fetch_ptr;
fetch_ptr = (COBOL_FUNC *) fetch(module);    /* loads fetched module */
fetch_ptr(args);         /* sets up the proper linkage for the call */

モジュールがフェッチされた後、フェッチされた関数を呼び出すと、言語間呼び出しを行うのと同様になります。

fetch() は、AMODE 切り替えもサポートします。つまり、この関数が呼び出されると、AMODE が切り替えられ、戻り時に AMODE が復元されます。フェッチされたモジュールが AMODE=24 で呼び出されたことがわかる と、基準以上の変数またはライブラリーへアクセスしようとします。

注 :
  1. fetchep() を使用する場合以外は、ロード・モジュール境界を超える 関数ポインターによって関数を呼び出すことはできません (詳細は、fetchep() - 書き込み可能静的変数の共用を参照してください)。例えば、関数のアドレスを、フェッチされたルーチンへ渡したり、フェッチされたルーチンから関数を呼び出したりすることはできません。z/OS C 書き込み可能静的変数はスワップされないためです。
  2. 制限されたアドレッシング・モード (AMODE 24 のような) で稼働しなければならないコードにアクセスする必要が ある場合は、コードをフェッチされるモジュール内にパックすることができます。そのモジュールを後に、制限されたアドレッシング・モードを使用してリンク することができますが、制限されないアドレッシング・モードでプログラムからフェッチされます。
  3. ロード・モジュールのすべてを解放しないで fetch() を何回も 呼び出すプログラムでは、メモリー不足になることがあります。

リンクに関する考慮事項: フェッチされる関数をリンクする際には、必要なライブラリーでリンクし、以下のディレクティブを含まない場合は、フェッチ中の関数として、エントリー・ポイン トを指定しなければなりません。#pragma linkage(…, FETCHABLE)

main() z/OS C 関数をリンクするとき、フェッチしようとする 関数を使用するために必要なライブラリーを指定する必要があります。例えば、COBOL 関数をフェッチしようとする場合は、COBOL ライブラリーを指定 します。この要件は、Language Environment には 該当しません

main() を実行するときは、フェッチする関数だけではなく、main() の ために必要となるランタイム・ライブラリーも指定してください。この要件は、Language Environment には 該当しません

C++ の特殊な動作: z/OS XL C++ プログラムでは、fetch() を呼び出すことができません。 z/OS XL C++ プログラム から fetch() を呼び出そうとすると、コンパイラーからエラー・メッセージ が発行されます。z/OS XL C++ で fetch() に 代わる方法として、以下の 3 とおりの方法があります。
  • fetch() を DLL (ダイナミック・リンク・ライブラリー) 呼び出しに 置き換えることができる。
  • CELEBF52 および CELEBF53 の例で示されているように、モジュールをフェッチするために C DLL モジュールを提供することができる。 を参照してください。
  • z/OS XL C++ プログラムは、z/OS XL C 関数を静的に呼び出すことができ、この関数が、次に別のモジュールをフェッチする。

戻り値

正常に実行された場合、fetch() は、フェッチされたロード・モジュールへのエントリー・ポイントを呼び出す、スタブへのポインターを戻します。

ロードが失敗した場合、fetch() は NULL を戻して、errno を以下のいずれかの値に設定する場合があります。

エラー・コード
定義
ELEFENCE
DLL は、オペレーティング・システムのこのバージョンではサポートされないメンバー言語を含んでいます。

C での fetch() 関数の使用例: 以下の例では、pragma linkage(…., FETCHABLE) ディレクティブを含む別の オブジェクト・モジュールで、関数をフェッチするプログラムをコンパイル 、リンク、および実行する方法を示します。

メインプログラムで始めます。
#include <stdio.h>
#include <stdlib.h>

typedef int (*funcPtr)();  /* pointer to a function returning an int */

int main(void)
{
    int result;
    funcPtr add;

    printf("fetch module¥n");
    add = (funcPtr) fetch("f1a");            /* load module F1A      */

    if (add == NULL) {
        printf("ERROR: fetch failed¥n");
    }
    else {
        printf("execute fetched module¥n");
        result = (*add)(1,2);                /* execute module F1A   */

        printf("1 + 2 == %d¥n", result);
    }
}
フェッチされる関数を以下に示します。
#pragma linkage(func1, fetchable)

int func1(int a, int b)
{
   printf("in fetched module¥n");

   return(a+b);
}
次に、MVS の下でコンパイル、リンクおよび実行する JCL を示します。
>
//F1A      EXEC EDCC,INFILE='userid.TEST.SOURCE(F1A)'
//         OUTFILE='userid.TEST.OBJ(F1A),DISP=SHR',
//         CPARM='NOSEQ,NOMARGIN,RENT'
//F1B      EXEC EDCPL,INFILE='userid.TEST.OBJ(F1A)'
//         OUTFILE='userid.TEST.LOAD(F1A),DISP=SHR'
//F1       EXEC EDCCLG,INFILE='userid.TEST.SOURCE(F1)'
//GO.STEPLIB DD
//           DD  DSN=userid.TEST.LOAD,DISP=SHR
以下の例では、COBOL での fetch() の使用方法、およびプログラムを コンパイルし、リンクして実行する方法を示します。
/* cob1 */
#include <stdlib.h>
#include <stdio.h>

typedef void funcV();           /* function returning void            */
#pragma linkage(funcV, COBOL)   /* establish Cobol linkage            */

int main(void)
{
    int var1 = 1;
    int var2 = 2;
    funcV *add;

    printf("fetch module¥n");
    add = (funcV *) fetch("cob1a");           /* load module COB1A    */

    if (add == NULL)
    {
        printf("ERROR: fetch failed¥n");
    }
    else
    {
        printf("execute fetched module¥n");
        (*add)(&var1, &var2);                 /* execute module COB1A */

        printf("1 + 2 == %d¥n", var1);
    }
}
以下は、フェッチされる COBOL サブルーチン COB1A です。
 IDENTIFICATION DIVISION.
 PROGRAM-ID.  COB1A.
****************************************************************
*   This subroutine receives 2 integer parameters.             *
*   The first is added to the second and the result is stored  *
*   back into the first.                                       *
****************************************************************
 ENVIRONMENT DIVISION.
 DATA DIVISION.

 WORKING-STORAGE SECTION.

 LINKAGE SECTION.
 01  VAR1                    PIC S9(9) COMP.
 01  VAR2                    PIC S9(9) COMP.
****************************************************************
*                  PROCEDURE DIVISION                          *
****************************************************************

 PROCEDURE DIVISION USING VAR1 VAR2.

*
*    ADD VAR2 TO VAR1 PLACING THE RESULT IN VAR1.
*

     COMPUTE VAR1 = VAR1 + VAR2.
           GOBACK.
最後に、MVS の環境でコンパイル、リンク、および実行します。
//*==================================================================
//COBCL  PROC CREGSIZ='2048K',
//            INFILE=,
// OUTFILE='&&GSET(GO),DISP=(MOD,PASS),UNIT=VIO,SPACE=(512,(50,20,1))'
//*
//*------------------------------------------------------------------
//* COBOL Compile Step
//*------------------------------------------------------------------
//COBCOMP EXEC PGM=IGYCRCTL,REGION=&CREGSIZ;
//STEPLIB  DD  DSNAME=IGY.V1R3M0.SIGYCOMP,DISP=SHR
//SYSPRINT DD  SYSOUT=*
//SYSIN    DD  DSNAME=&INFILE,DISP=SHR
//SYSLIN   DD  DSNAME=&&LOADSET,UNIT=SYSDA,
//             DISP=(MOD,PASS),SPACE=(TRK,(3,3)),
//             DCB=(BLKSIZE=3200)
//SYSUT1   DD  UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT2   DD  UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT3   DD  UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT4   DD  UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT5   DD  UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT6   DD  UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT7   DD  UNIT=SYSDA,SPACE=(CYL,(1,1))
//*
//*------------------------------------------------------------------
//* COBOL Link-Edit Step
//*------------------------------------------------------------------
//COBLINK EXEC PGM=HEWL,COND=(8,LT,COBCOMP),REGION=1024K
//SYSLIB   DD  DSNAME=CEE.V1R3M0.SCEELKED,DISP=SHR
//SYSPRINT DD  SYSOUT=*
//SYSLIN   DD  DSNAME=&&LOADSET,DISP=(OLD,DELETE)
//         DD  DDNAME=SYSIN
//SYSLMOD  DD  DSNAME=&OUTFILE;
//SYSUT1   DD  UNIT=SYSDA,SPACE=(TRK,(10,10))
// PEND
//*
//*==================================================================
//* Compile and Link-Edit COBOL program COB1A
//*------------------------------------------------------------------
//COB1A   EXEC COBCL,
//         INFILE='userid.TEST.SOURCE(COB1A)',
//         OUTFILE='userid.TEST.LOAD(COB1A),DISP=SHR'
//COBLINK.SYSIN DD *
 ENTRY COB1A
/*
//*
//*------------------------------------------------------------------
//* Compile and Link-Edit C program COB1
//*------------------------------------------------------------------
//COB1    EXEC EDCCLG,
//         INFILE='userid.TEST.SOURCE(COB1)',
//         CPARM='OPT(0) NOSEQ NOMAR'
//GO.STEPLIB DD
//           DD DSNAME=userid.TEST.LOAD,DISP=SHR

C++ での fetch() の代替例: この例は、fetch() の代わりとして DLL を使用する場合の DLL の使い方を示します。 ここで、myfunc() は DLL を使用して動的にロードされる関数で 、main() は DLL を呼び出します。

CELEBF52
⁄⁄ CELEBF52-part 1 of 2-other file is CELEBF53.

⁄⁄ This example shows how to use DLL as an alternative to fetch().

⁄⁄ C++ program that invokes myfunc using DLL

#include <stdlib.h>
#include <stdio.h>
#include <dll.h>

extern "C" {           ⁄⁄ needed to indicate C linkage
  typedef int (*funcPtr)(); ⁄⁄ pointer to a function returning an int
}

int main (void)
{
  dllhandle *dllh;
  funcPtr   fptr;

  if ((dllh = dllload( "celebf53" )) == NULL) {
     perror( "failed to load celebf53" );
     exit( -1 );
  }
  if ((fptr = (funcPtr) dllqueryfn( dllh, "myfunc" )) == NULL) {
     perror( "failed to retrieve myfunc" );
     exit( -2 );
  }
  if ( fptr() != 0 ) {
     perror( "failed to execute myfunc" );
     exit( -3 );
  }
  if ( dllfree( dllh ) != 0 ) {
     perror( "failed to free celebf53" );
     exit( -4 );
  }
  return( 0 );
}
CELEBF53
⁄* CELEBF53-part 2 of 2-other file is CELEBF52.

   This example shows how to use DLL as an alternative to fetch().

 *⁄

⁄*

  C function dynamically loaded using DLL

 *⁄

#include <stdio.h>

int myfunc (void)
{
  printf( "Hello world¥n" );
  return( 0 );
}

次の例では、C++ プログラムが C DLL モジュール内の関数を動的に呼び出して、別の C モジュールをフェッチする方法を示します。

CELEBF54
// CELEBF54-part 1 of 3-other files are CELEBF55, CELEBF56.
// This example shows how a C++ program can dynamically call a function
// in a C DLL module, to fetch other C modules

// C++ program that dynamically calls a function in a C DLL module

#include <stdio.h>
#include <stdlib.h>
#include <dll.h>
#include <iostream.h>

extern "C" {           // needed to indicate C linkage
  typedef int (*funcPtr)(); // pointer to a function returning an int
}

int main (void)
{
  dllhandle *dllh;
  funcPtr   fptr;

  if ((dllh = dllload( "mydll" )) == NULL) {
     perror( "failed to load mydll" );
     exit( -1 );
  }
  if ((fptr = (funcPtr) dllqueryfn( dllh, "fwrap" )) == NULL) {
     perror( "failed to retrieve fwrap" );
     exit( -2 );
  }
  if ( fptr() != 0 ) {
     perror( "failed to execute fwrap" );
     exit( -3 );
  }
  if ( dllfree( dllh ) != 0 ) {
     perror( "failed to free mydll" );
     exit( -4 );
  }
  return( 0 );
}
CELEBF55
/* CELEBF55-part 2 of 3-other files are CELEBF54, CELEBF56.
   This example shows how a C++ program can dynamically call a function
   in a C DLL module, to fetch other C modules

   fwrap function used in a DLL module-it fetches mymod, which
   contains myfunc
 */
#include <stdio.h>
#include <stdlib.h>

typedef int (*funcPtr)();   /* pointer to a function returning an int */

int fwrap (void)
{
  funcPtr   fptr;

  if ((fptr = (funcPtr) fetch( "mymod" )) == NULL) {
     perror( "failed to fetch mymod" );
     return( -1 );
  }
  else
     return(fptr());
}
CELEBF56
/* CELEBF56-part 3 of 3-other files are CELEBF54, CELEBF55.
   This example shows how a C++ program can dynamically call a function
   in a C DLL module, to fetch other C modules
 */

/*    C function to be fetched   */

#include <stdio.h>
#pragma linkage(myfunc, fetchable)

int myfunc (void)
{
  printf( "in fetched module¥n" );
  return( 0 );
}

以下の例では、別の関数をフェッチする代わりに、C 関数を静的に呼び出す方 法を示しています。ここで、myfunc() はフェッチされる関数で、fetcher() は myfunc() をフェッチする C 関数で、main() は fetcher() を静的に呼び出す関数です。

CELEBF57
// CELEBF57-part 1 of 3-other files are CELEBF58, CELEBF59.
// This example shows how to statically call a C function that
// fetches other functions.

// C++ statically calling a C program that uses fetch()

#include <iostream.h>

extern "C" {          //  needed to indicate C linkage
  int fetcher (void);
}

int main (void)
{
  cout << "The fetcher says: ";
  fetcher();
  cout << "and returns";
  return( 0 );
}
CELEBF58
/* CELEBF58-part 2 of 3-other files are CELEBF57, CELEBF59.
   This example shows how to statically call a C function that fetches
   other functions.
 */

/*
   C function that fetches mymod which contains myfunc
 */
#include <stdio.h>
#include <stdlib.h>

typedef int (*funcPtr)();   /* pointer to a function returning an int */

int fetcher (void)
{
  funcPtr fptr;

  if ((fptr = (funcPtr) fetch( "mymod" )) == NULL) {
     perror( "failed to fetch mymod" );
     return( -1 );
  }
  else {
     fptr();                /* invoke fetched function */
     return( 0 );
  }
}
CELEBF59
/* CELEBF59-part 3 of 3-other files are CELEBF57, CELEBF58.
   This example shows how to statically call a C function that fetches
   other functions.
 */

/*    C function to be fetched    */

#include <stdio.h>
#pragma linkage(myfunc, fetchable)

int myfunc (void)
{
  printf( "Hello world " );
  return( 0 );
}

DLL のフェッチや使用は機能的には互換性がありますが、微妙な違いがあります。静的変数やグローバル変数の新しいコピーは、フェッチされるモジュールを毎回割り振 りますが、同じモジュールの DLL ロードは毎回は行われません。

以下の例では、モジュールが複数回フェッチされるとき、静的変数やグローバル変数の新しいコピーが割り振られる様子を示します。

CELEBF60
/* CELEBF60-part 1 of 2-other file is CELEBF61.
   This example shows how copies of variables are allocated when multiple
   fetches are done.
 */

/*
   C program fetching mymod multiple times--mymod contains myfunc.
 */
#include <stdio.h>
#include <stdlib.h>

typedef int (*funcPtr)(int); /*pointer to a function returning an int*/

int main (void)
{
  funcPtr fptr1, fptr2;

  if ((fptr1 = (funcPtr) fetch( "mymod" )) == NULL) {
     perror( "failed to fetch mymod" );
     return( -1 );
  }
  if ( fptr1(100) != 0 ) {
     perror( "failed to execute myfunc" );
     exit( -2 );
  }
  if ((fptr2 = (funcPtr) fetch( "mymod" )) == NULL) {
     perror( "failed to fetch mymod" );
     return( -3 );
  }
  if ( fptr2(100) != 0 ) {
     perror( "failed to execute myfunc" );
     exit( -4 );
  }
  return( 0 );
}
CELEBF61
/* CELEBF61-part 2 of 2-other file is CELEBF60.
   This example shows how copies of variables are allocated when multiple
   fetches are done.
 */

/*     C module mymod    */
#include <stdio.h>
#pragma linkage(myfunc, fetchable)

int globvar = 5;

int myfunc (int x)
{
  globvar += x;
  printf( "%d¥n", globvar );
  return( 0 );
}
この例を実行すると、以下のような結果が得られます。
105
105

以下の例では、同じモジュールの DLL の複数回ロードに対しては、静的変数やグローバル変 数の新しいコピーが割り振られない様子を示します。

CELEBF62
// CELEBF62-part 1 of 2-other file is CELEBF63.
// This example shows how copies of variables are allocated when
// multiple DLL loads are done.

// C++ program doing multiple DLL loads of the same module

#include <stdlib.h>
#include <stdio.h>
#include <dll.h>

extern "C" {                   //needed to indicate C linkage
  typedef int (*funcPtr)(int); //pointer to a function returning an int
}

int main (void)
{
  dllhandle *dllh1, *dllh2;
  funcPtr fptr;

  if ((dllh1 = dllload( "mydll" )) == NULL) {
     perror( "failed to load mydll" );
     exit( -1 );
  }
  if ((fptr = (funcPtr) dllqueryfn( dllh1, "myfunc" )) == NULL) {
     perror( "failed to retrieve myfunc" );
     exit( -2 );
  }
  if ( fptr(100) != 0 ) {
     perror( "failed to execute myfunc" );
     exit( -3 );
  }
  if ((dllh2 = dllload( "mydll" )) == NULL) {
     perror( "failed to load mydll" );
     exit( -4 );
  }
  if ((fptr = (funcPtr) dllqueryfn( dllh2, "myfunc" )) == NULL) {
     perror( "failed to retrieve myfunc" );
     exit( -5 );
  }
  if ( fptr(100) != 0 ) {
     perror( "failed to execute myfunc" );
     exit( -6 );
  }
  if ( dllfree( dllh1 ) != 0 ) {
     perror( "failed to free mydll" );
     exit( -7 );
  }
  return( 0 );
}
CELEBF63
/* CELEBF63-part 2 of 2-other file is CELEBF62.
   This example shows how copies of variables are allocated when multiple
   DLL loads are done.
 */

/* C function invoked using DLL */

#include <stdio.h>
#include <stdlib.h>

int globvar = 5;
int myfunc (int);

int myfunc (int x)
{
  globvar += x;
  printf( "%d¥n", globvar );
  return( 0 );
}
この例を実行すると、以下のような結果が得られます。
105
205

関連情報