Modern Fortran Explained - 2018
Fortran2018 で導入された Fortran と C の interoperability について、少しづつ試してゆきたいと思います。 MFE にはコード断片しかないので、残りを適当に埋めて、実行可能な形にして試していみることにします。
§ 21.2 Fortran optinal 引数と C 言語の通用
C 言語の関数 strtod (string to double) をインターフェースだけ書いて呼び出します。C 言語には文法上 optional 引数は無いのですが、null を送ることで optional 引数を実現しているようです。組み込みライブラリ関数 strtod はそのような仕組みを用いているようです。
参照: C言語関数辞典 - strtod
strtod は第一引数に文字列を与えると、その文字列先頭部を倍精度の数値として解釈して倍精度実数として返します。第二引数は optional で、ポインタを与えると、数値として解釈できなくなったところから文字列を返します。
ソース・プログラム
ポインタを Fortran 文字列にするのがこれでいいのかどうか。
module test_m
implicit none
interface
function strtod(string, final) bind(c, name='strtod')
use, intrinsic :: iso_c_binding
character(kind=c_char), intent(in) :: string(*)
type(c_ptr), optional, intent(in) :: final
real(c_double) :: strtod
end function strtod
end interface
end module test_m
program main
use, intrinsic :: iso_c_binding
use test_m
implicit none
real(c_double) :: x, y
type(c_ptr) :: yfinal
character(80), pointer :: text
x = strtod("3.1415926e2"//c_null_char)
y = strtod("3.1415926d2"//c_null_char, yfinal)
print *, x
print *, y
call c_f_pointer(yfinal, text)
print *, text(:index(text, c_null_char) - 1)
end program main
実行結果
3.1415926e2 は e2 が 102 と解釈されましたが、3.1415926d2 は d2 の部分が解釈されずに吐き出されました。
gfortran 7,8,9
hp8@HP8:~/f2018$ gfortran-7 strtod.F90
hp8@HP8:~/f2018$ ./a.out
314.15926000000002
3.1415926000000001
d2
ifort 19 文字列でない・・・
314.159260000000
3.14159260000000
C から Fortran の optional 引数を使う場合
ソース・プログラム
module test_m
implicit none
contains
subroutine fortran_note(main, minor) bind(c, name='fortran_note')
use, intrinsic :: iso_c_binding
integer(c_int), value :: main
integer(c_int), optional :: minor
if (present(minor)) then
print '(1x, "Note ", I0, ".", I0)', main, minor
else
print '(1x, "Note ", I0)', main
end if
end subroutine fortran_note
end module test_m
void fortran_note(int main, int* minor);
int main(void) {
fortran_note(10, (int *)0);
int subnote = 3;
fortran_note(10, &subnote);
return 0;
}
実行結果
gfortran 7,8,9
hp8@HP8:~/f2018$ gfortran c_note.c note.f90
hp8@HP8:~/f2018$ ./a.out
Note 10
Note 10.3
ifort/icc 適せつなリンクの仕方が分からない・・・
icc からは fortran I/O ランタイムが呼べず、ifort では main が無いと言われる・・・