この作業の中で学んだことを忘れないように書いておく。
subrouitine func(x)ここで、x はフィルする値、w は重みである。この xhfill の実体を C++ で書かれた JSFBases クラスのメンバー関数(JSFBases::H1Fill)にしたいわけである。
implicit real*8 (a-h,o-z)
external xhfill
.........
call xhfill('h01', x, w)
.........
return
JSFBases *bso; // これは H1Fill をメンバー関数とする JSFBases オブジェクトへのポインターFORTRAN 関数名にはアンダースコアーがつけられること、引数が全て値でなくアドレスわたしであること、そして FORTRAN の文字列の扱いの特殊性に注意(FORTRAN では文字列はヌルターミネートされておらず、そのかわりに文字列の長さを、FORTRAN では見えない引数でわたす。従って C または C++ にその文字列をわたす際にはヌルターミネートしてから、その長さといっしょにわたす必要がある)。
extern "C" { // これでシンボル名がマングルされないので、FORTRAN から見える
void xhfill_(char *t, double *x, double *w, int len) // xhfill の後のアンダースコアー、
{ // 文字列の長さを保持する引数 len に注意。
char tmp[1024]; // また、引数は全てアドレスわたしである。
int i;
for (i=0; i<len; i++) tmp[i] = t[i];
tmp[len] = '\0'; // FORTRAN の文字列はヌルターミネートされていない
bso->H1Fill(tmp,*x,*w); // 実行時、bso は確定しているのでメンバー関数が呼び出せる
}
}
jSFBases::JSFBases(......) : .....のようにセットする。スタティック関数なら bso->H1Fill(tmp,*x,*w) のようにポインターを使うのでなく、JSFBases::H1Fill(tmp,*x,*w) のように書けばよい。
{
.....
bso = this;
.....
}
subroutine subfort(i,x,str1,array,str2)なる FORTRAN 関数は、
integer*4 i
real*4 x
character*(*) str1, str2
......
return
end
extern "C" {などとしておけば良い。もちろん、これを C++ から呼ぶ際にはアドレスわたしであることに注意し、len1 と len2 もセットして呼ばねばならない。
extern void subfort_(int *i, float *x, char *str1, float array[],
char *str2, int len1, int len2);
......
}
int i = 0;のような感じ。
float x =1.;
float array[] = {0., 1., 2.};
char *str1 = ".....";
char *str2 = ".....";
......
subfort_(&i, &x, str1, array, str2, strlen(str1), strlen(str2));
common /fcom/ i, x, y, a(100)まず
integer*4 i
real*4 x, y, a
extern "C" {などと宣言し、
typedef struct {
int i;
float x;
float y;
float a[100];
} COMMON_fcom;
}
COMMON_fcom fcom_;後は、C++ のプログラムの中で
fcom_.i = 1;などとすればよい。
fcom_.a[10] = 0.5;
float x = fcom_.x;