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
- 作者: Michael Metcalf,John Reid,Malcolm Cohen
- 出版社/メーカー: Oxford Univ Pr
- 発売日: 2018/11/06
- メディア: ハードカバー
- この商品を含むブログを見る
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 適せつなリンクの仕方が分からない・・・