インテル® 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 言語が最適です。
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 から渡される引数を示します。
関数は 4 バイト整数 (int) として宣言する必要があります。
第 1 引数は、開かれるパス名 (ファイル名を含む) です。
オープンフラグについては、/usr/include/sys/file.h ヘッダファイルまたは open(2) で説明されています。
作成モード (ファイルの作成時に必要な保護) については、open(2) で説明されています。
第 4 引数は 論理ユニット番号です。
最後の第 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 プロシージャを呼び出します。
インテル Fortran RTL は、1 つの論理ユニットごとにファイル記述子を 1 つだけ使用します。ファイル記述子は、呼び出された関数によって返される必要があります。このため、ファイルを開く際に使用できるのは、特定のシステムコールまたはライブラリ・ルーチンだけです。
ファイル記述子を返さないシステムコールおよびライブラリ・ルーチンには、mknod (mknod(2) を参照) および fopen (fopen(3) を参照) があります。例えば、fopen ルーチンはファイル指定子の代わりにファイルポインタを返します。
次のインテル 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_ として宣言する必要があります。
icc コマンドを使用して、呼び出される C の uopen_ 関数 (uopen_.c) をコンパイルします。また、ifort コマンドを使用して、インテル Fortran の呼び出しプログラム (ex1.f) をコンパイルします。 この ifort コマンドはまた、次のように、適切なライブラリを使用することで、両方のオブジェクト・ファイルをリンクし、a.out ファイルを作成します。
icc -c uopen_.c
ifort ex1.f uopen_.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 */
次に、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