// myheader.h #define PI 3.141592653 double ratio=1.0; double PieArea( double radius ) { double area; area = PI*radius*radius*ratio; return( area ); }
ヘッダーファイル内の記述の仕方はいつも通りである。この中の関数が stdio.h などの他の関数を使う場合にはこのヘッダーファイル内で #include <stdio.h> としておくほうが良い。 main.cc は myheadr.h を #include "" で取り込む。 main.cc をコンパイルすると myheader.h の内容がここに展開されて適切にコンパイルされる。// main.cc #include <stdio.h> #include "myheader.h" int main( void ) { double r, a; r = 1.0; ratio = 0.25; a = PieArea( r ); return(0); }
これで、関数 PieArea() と global変数 ratio は #include するだけで他のプログラムからも利用できる。 これがもっとも簡単なプログラムの分割例であるが、これだけではまだ モジュールとは呼べない。
// myheader.h #ifndef __MYHEADER_H_INCLUDE #define __MYHEADER_H_INCLUDE extern double ratio; double PieArea( double radius ); #endif //__MYHEADER_H_INCLUDE
ファイルの先端と終端の #ifndef 、 #define と #endif は、コンパイル時にこのヘッダーファイル内の諸宣言が不必要に何度も宣言 されるのを防止する小細工である。// myheader.cc #include "myheader.h" #define PI 3.141592653 double ratio=1.0; double PieArea( double radius ) { double area; area = PI*radius*radius*ratio; return( area ); }
global変数の宣言には extern を冠する。変数 ratio の実体は まだ存在しないが、以後に登場するものとして、コンパイラは作業を続ける。 実体がないので値を代入することはできない。関数の宣言もprototypeのみで あり、これもその実体が以後に定義されるものとしてコンパイラは作業を 続ける。
主モジュールファイル main.cc は先のものと同じである。 コンパイルは次の様に各モジュールごとに行う。
両方のコンパイルで myheader.h が読み込まれ適切な判断が行われる。 -c オプションはコンパイラに実行ファイルを作らせずに オブジェクトファイルと呼ばれる中間ファイルを生成させる。 この例では myheader.o と main.o となる。gcc -c myheader.cc gcc -c main.cc
次にこのふたつのオブジェクトファイルをリンクしてひとつの 実行ファイルを作る。
これで出来上がりである。 以後、 main.cc を変更したらそれだけを上の手順でコンパイルして 既にある myheader.o とリンクすれば良い。逆も同じである。 こうしてコンパイル作業を効率化することができる。gcc -o main main.o myheader.o
gcc の行の行頭はタブであることに気を付けよう。 1行目の all: に続く main はこの makefile が 生成すべき最終ターゲットが main であることを示す。 3行目の myheader.o: とそれに続く2つのファイル名は myheader.o がこの2つのファイルの内容を汲んで生成されることを 示し、この2つのファイルのどちらかが更新されていたら次の行の コマンドを実行する。以下同様である。 結局、この記述によりmakeは変更箇所だけを自動的に コンパイルしてくれるのである。all: main myheader.o: myheader.c myheader.h gcc -c myheader.c main.o: main.c myheader.h gcc -c main.c main: main.o myheader.o gcc -o main main.o myheader.o
こうして巨大なプログラムもモジュールごとに作成され、 最後にmakeでひとつの実行ファイルとなるのである。
FORTRAN | C言語 |
Character | char |
Integer*2 | short |
Integer | long |
Logical | long |
Real | float |
Double Precision | double |
FORTRAN | C言語 |
Character*16 | 16文字の文字配列 |
Complex | struct{ float real, imag; } |
Double Complex | struct{ double real, imag; } |
例えば次のFORTRANのNAGライブラリのサブルーチンがある。
これをC言語またはC++で利用するには、ますprototype宣言を それぞれ次の様にする。Subroutine C06EAF(X, N, IFAIL) Integer N, IFAIL Double Precision X(N)
そして呼び出しは以下の通りである。void c06eaf_( double x[], int *n, int *ifail ); // C extern "C" void c06eaf_( double x[], int& n, int& ifail ); // C++
c06eaf_( x, &n, &ifail ); // C c06eaf_( x, n, ifail ); // C++
例えば次のFORTRANのNAGライブラリの関数がある。
prototype宣言と呼び出しはは以下の通りである。Character*30 Function X05ABF (ITIME) Integer ITIME(7)
FORTRANが返す文字列にはNULL終端子( '\0' )が付かないので C言語側で補うことに注意しよう。void x05abf_( char str[], int len, int n[] ); // C extern "C" void x05abf_( char str[], int len, int n[] ); // C++ char str[31]; x05abf_( str, 30, n ); // both C & C++ str[30]='\0';
リンクすべきライブラリは環境によってこれとは異なるかもしれない。gcc -o main main.cc fobj.o -lF77 -lI77