ユーザが提供する OPEN プロシージャ: USEROPEN 指定子

インテル® Fortran の OPEN 文で USEROPEN 指定子を使用して、ファイルを直接開くルーチンに制御を渡すことができます。呼び出されたルーチンでは、システムコールまたはライブラリ・ルーチンを使用することで、ファイルを開き、後続のインテル Fortran I/O 文の効果を変更する特別なコンテキストを確立することができます。

インテル Fortran RTL I/O サポートルーチンでは、I/O のためにファイルが最初に開かれたときに通常使用されるシステムコールの代わりに、USEROPEN 関数を呼び出します。OPEN 文の USEROPEN 指定子では、制御を受け取る関数の名前を指定します。呼び出された関数は、ファイル (またはパイプ) を開いて、RTL に制御を戻す際にそのファイルのファイル記述子を返す必要があります。

ファイルを開く際に呼び出された関数では、通常、標準の OPEN 文で指定されるものとは異なるオプションを指定します。

getfd ルーチンを使用して、インテル Fortran RTL から特定のユニット番号のファイル記述子を取得することができます。

呼び出された関数は、C 以外の言語 (Fortranなど) で記述することができますが、通常、open または create などのシステムコールの作成には、C 言語が最適です。

USEROPEN 指定子の構文および動作

OPEN 文の USEROPEN 指定子の形式は次のとおりです。

USEROPEN = function-name

function-name の値は外部関数の名前を示します。呼び出すプログラム側では、この関数は EXTERNAL 文で宣言する必要があります。例えば、次のインテル Fortran コードを使用して、UOPEN という名前の USEROPEN プロシージャ (リンカでは uopen_ として認識されます) を呼び出します。

EXTERNAL  UOPEN

INTEGER   UOPEN

.

.

.

OPEN (UNIT=10, FILE='/usr/test/data', STATUS='NEW', USEROPEN=UOPEN)

OPEN 文が実行されるとuopen_ 関数は制御を受け取ります。関数はファイルを開き、指定された操作を実行し、そして RTL に制御 (およびファイル記述子) を返します。

USEROPEN 関数が C で記述されている場合、ファイル記述子を格納するために、この関数を 4 バイト整数 (int) の結果を返す C の関数として宣言します。次に例を示します。

int   uopen_ (                (1)
     char  *file_name,       (2)
     int   *open_flags,      (3)
     int   *create_mode,     (4)
     int   *lun,             (5)
     int   file_length);     (6)

次に、関数の定義およびインテル Fortran RTL から渡される引数を示します。

  1. 関数は 4 バイト整数 (int) として宣言する必要があります。

  2. 第 1 引数は、開かれるパス名 (ファイル名を含む) です。

  3. オープンフラグについては、/usr/include/sys/file.h ヘッダファイルまたは open(2) で説明されています。

  4. 作成モード (ファイルの作成時に必要な保護) については、open(2) で説明されています。

  5. 第 4 引数は 論理ユニット番号です。

  6. 最後の第 5 引数は、パス名の長さ (パス名の長さの隠し引数) です。

open システムコール (open(2) を参照) では、渡されたパス名、オープンフラグ (必要なアクセスタイプやファイルが存在するかどうかなどを定義)、および作成モードが必要です。OPEN 文で指定された論理ユニット番号は、USEROPEN 関数で必要となる場合に備えて渡されます。また、パス名の長さの隠し引数も渡されます。

新しいファイルを作成する場合、open システムコールの代わりに create システムコールを使用することができます (create(2) を参照)。通常は、USEROPEN 関数内でその他の適切なシステムコールまたはライブラリ・ルーチンを使用することができます。

ほとんどの場合、USEROPEN 関数はインテル Fortran RTL によって渡されたオープンフラグ引数を変更するか、open (または create) システムコールの前に新しい値を使用します。関数は、ファイルを開いた後で RTL に制御を返す必要があります。

USEROPEN 関数が Fortran で記述されている場合、その関数を INTEGER (KIND=4) の結果 (場合によっては、インターフェイス・ブロック) を返す FUNCTION として宣言します。呼び出された関数は、RTL に 4 バイト整数のファイル記述子を返す必要があります。

C 言語を使用してファイルの開閉、およびすべてのレコード操作を行う必要があるアプリケーションでは、Fortran の OPEN 文を使用せずに、インテル Fortran プログラムから適切な C プロシージャを呼び出します。

呼び出された USEROPEN 関数の制限事項

インテル Fortran RTL は、1 つの論理ユニットごとにファイル記述子を 1 つだけ使用します。ファイル記述子は、呼び出された関数によって返される必要があります。このため、ファイルを開く際に使用できるのは、特定のシステムコールまたはライブラリ・ルーチンだけです。

ファイル記述子を返さないシステムコールおよびライブラリ・ルーチンには、mknod (mknod(2) を参照) および fopen (fopen(3) を参照) があります。例えば、fopen ルーチンはファイル指定子の代わりにファイルポインタを返します。

USEROPEN プログラムおよび関数の例

次のインテル Fortran コードは、UOPEN という名前の USEROPEN 関数を呼び出します。

EXTERNAL  UOPEN
INTEGER   UOPEN

 .

 .

 .
OPEN (UNIT=1,FILE='ex1.dat',STATUS='NEW',USEROPEN=UOPEN, ERR=9,IOSTAT=errnum)

デフォルトの ifort オプションが使用される場合、外部名には小文字が使用され、その名前の最後に下線 (_) を付加して渡されます。上記の例では、外部関数 UOPEN は、リンカは uopen_ として認識し、C の中では uopen_ として宣言する必要があります。

C およびインテル Fortran プログラムのコンパイルとリンク

icc コマンドを使用して、呼び出される C の uopen_ 関数 (uopen_.c) をコンパイルします。また、ifort コマンドを使用して、インテル Fortran の呼び出しプログラム (ex1.f) をコンパイルします この ifort コマンドはまた、次のように、適切なライブラリを使用することで、両方のオブジェクト・ファイルをリンクし、a.out ファイルを作成します。

icc -c uopen_.c
ifort ex1.f uopen_.c

C 関数およびヘッダファイル用のソースコード

次に、uopen_ という名前の C 言語の関数および関連するヘッダファイルを示します。

/*

** File: uopen.h -- header file for uopen_.c
*/

#ifndef UOPEN
#define UOPEN 1
/*
**
**    Function Prototypes
**
*/
int   uopen_ (
     char  *file_name,    /* access read: name of the file to open. */
     int   *open_flags,   /* access read: READ/WRITE, see file.h or open(2)*/
     int   *create_mode,  /* access read: set if new file (to be created).*/
     int   *lun,          /* access read: logical unit file opened on.*/
     int  file_length);   /* access read: number of characters in file_name*/

#endif

/* End of file uopen.h */

/*
** File: uopen_.c
*/

/*
** This routine opens a file using data passed by Intel Fortran RTL.
**
**  INCLUDE FILES
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include "uopen.h"/* Include file for this module */

int uopen_ (file_name, open_flags, create_mode, lun, file_length)

/*
** Open a file using the parameters passed by the calling Intel
**   Fortran program.
**
**  Formal Parameters:
*/

char  *file_name;    /* access read: name of the file to open. */
int   *open_flags;   /* access read: READ/WRITE, see file.h */
int   *create_mode;  /* access read: set if new file (to be created). */
int   *lun;          /* access read: logical unit number file opened on. */
int   file_length;   /* access read: number of characters in file_name. */

/*
**  Function Value/Completion Code
**
** Whatever is returned by open is immediately returned to the
** Fortran OPEN.  The returned value is the following:
**    value >= 0 is a valid fd.
**    value <  0 is an error.
**
**  Modify open flags (logical OR) to specify the file be opened for
**  write access only, with records appended at the end (such as
**  writing to a shared log file).
*/

{
      int    result ;           /* Function result value */

      *open_flags =                 
            O_CREAT  |
            O_WRONLY |
            O_APPEND;

     result = open (file_name, *open_flags, *create_mode) ;

      return (result) ;         /* return file descriptor or error */

      }/* End of routine uopen_ */

     /* End of file uopen_.c */

インテル Fortran プログラムを呼び出すソースコード

次に、C の uopen_ 関数を呼び出して、その後 I/O を実行する Fortran プログラムを示します。

!
!  Program EX1 opens a file using USEROPEN and writes records to it.
!  It closes and re-opens the file (without USEROPEN) and reads 10 records.
PROGRAM EX1

    EXTERNAL    UOPEN         ! The USEROPEN function.
    INTEGER     ERRNUM, CTR, I

1   FORMAT (I)
    ERRNUM = 0
    WRITE (6,*) 'EX1. Access data using formatted I/O.'
    WRITE (6,*) 'EX1. Open file with USEROPEN and put some data in it.'

   OPEN (UNIT=1, FILE='ex1.dat', STATUS='NEW', USEROPEN=UOPEN, ERR=9,IOSTAT=errnum)
    DO CTR=1,10
     WRITE (1,1) CTR
    END DO
    WRITE (6,*) 'EX1. Close and re-open without USEROPEN.'
    CLOSE (UNIT=1)
    OPEN (UNIT=1, FILE='ex1.dat', STATUS='OLD', FORM='FORMATTED', ERR=99, IOSTAT=errnum)
    WRITE (6,*) 'EX1. Read and display what is in file.'
    DO CTR=1,10
       READ (1,1) i
       WRITE (6,*) i
    END DO
    WRITE (6,*) 'EX1.  Successful if 10 records shown.'
    CLOSE (UNIT=1,STATUS='DELETE')
    STOP
  9 WRITE (6,*) 'EX1.  Error on USEROPEN is ', errnum
    STOP
 99 WRITE (6,*) 'EX1.  Error on 2nd open is ', errnum
END PROGRAM EX1