Closed wistaria closed 4 years ago
エラーが出ているのは、動的にサイズを指定できる文字列の宣言部分です。 (Fortranも文字列は、character型の配列ではなく、1個のスカラー。)
そのため、gfortran4.8以前のものは、切り捨てたいです。。。
京やFX10の frtpx では Fortran2003 はサポートされていますか?そうであれば Fortran2003 以前は切り捨てて良いと思います。
CMake で Fortran2003 がサポートされているかどうかチェックして、サポートされていない場合には BUILD_Fortran_BINDING を自動的に OFF にすることはできますか?
はい、できると思います。
対策:
以下はコンパイルは通るが、seg faultとなる。
program main
implicit none
character(len=:), allocatable :: tmp
if (command_argument_count() >= 1) then
call get_command_argument(1, tmp)
endif
print *,tmp
end program main
ルーチンget_command_argument
のラッパーを書いた。
program main
implicit none
character(len=:), allocatable :: tmp
if (command_argument_count() >= 1) then
call get_command_argument_deffered(1, tmp)
print *,tmp
endif
contains
subroutine get_command_argument_deffered(i, str)
implicit none
integer, intent(in) :: i
character(len=:), allocatable, intent(out) :: str
integer :: arg_len
call get_command_argument(i, length=arg_len)
allocate(character(arg_len) :: str)
call get_command_argument(i, value=str)
end subroutine get_command_argument_deffered
end program main
今や、文字列のdeferred lengthは、全てのFortranコンパイラ実装されている。 この使用をデフォルトとした。
094d6bb56babe7c4800b67159d2473a4aaafca31
変更案:
rokko_serial_dense_ev_default_solverは、subroutineからfunctionに変更する。 戻り値型は、len=とする。 すると、左辺型が、len=とlen=:のどちらの場合も使えるはず。 len=:の場合は、automatically allocating suitable sizeとなるため。
std::stringの.size()を使えば、末尾のヌル文字を検出しなくても良くなる。 この場合、Fortranバインディング用のCラッパー関数が必要となる。(Cバインディングでは使えない関数である。)
"Modern Fortran Explained (5th edition)"のp.109 Sec. 6.7 "Automatic reallocation"
program main
implicit none
interface
function getcstr() bind(c, name="getcstr")
use, intrinsic :: iso_c_binding
type(c_ptr) :: getcstr
end function getcstr
end interface
print *, cstr2f(getcstr())
contains
function cstr2f(s)
use, intrinsic :: iso_c_binding
interface
pure function strlen(s) bind(c, name="strlen")
use, intrinsic :: iso_c_binding
type(c_ptr), intent(in) :: s
integer(c_size_t) :: strlen
end function strlen
end interface
type(c_ptr), intent(in) :: s
character(kind=c_char, len=strlen(s)), pointer :: cstr2f
call c_f_pointer(s, cstr2f)
end function cstr2f
end program main
const char* getcstr(void) {
return "Hello!";
}
C言語の組み込み関数"strlen"をinterface宣言して、用いている。 これは、どのコンパイラでも使用可能か?
戻り値は、以下の3つに、自動で変換できる。
program main
implicit none
character(len=:), allocatable :: str
character(len=:), pointer :: ptr
character(len=100), allocatable :: f_str
interface
function getcstr() bind(c, name="getcstr")
use, intrinsic :: iso_c_binding
type(c_ptr) :: getcstr
end function getcstr
end interface
print *, cstr2f(getcstr())
str = cstr2f(getcstr())
print *, "str=", str
ptr => cstr2f(getcstr())
print *, "ptr=", ptr
f_str = cstr2f(getcstr())
print *, "f_str=", f_str
value
属性を付けないと、strlenが5や3になる。
type(c_ptr), intent(in), value :: s
https://www.nag-j.co.jp/fortran/tips/tips_InteroperabilityWithC.html#FcGetCsPtr
"Modern Fortran Explained (5th edition)"のp.410 Sec.21.6.5 Allocatable objects
以下は、Fortran 2008の機能なので、まだ使えない。
sakashitatatsuyanoMacBook-puro% gfortran string.f90 -c [~/try/fortran]
string.f90:39:24:
call c_f_pointer(s, cstr2f, strlen(s))
1
Error: Unexpected SHAPE argument at (1) to C_F_POINTER with scalar FPTR
a8d694c1bfad2da59852d9377c4a5df5b57dce93
$ make [ 42%] Built target lapacke [ 42%] Building Fortran object rokko/CMakeFiles/rokko.dir/string.F90.o /home/wistaria/development/rokko/rokko/string.F90:6.19:
Error: Syntax error in CHARACTER declaration at (1) /home/wistaria/development/rokko/rokko/string.F90:30.18:
Error: Syntax error in CHARACTER declaration at (1) /home/wistaria/development/rokko/rokko/string.F90:26.43:
subroutine rokko_get_string (str_ptr, val) 1 Error: Symbol 'val' at (1) has no IMPLICIT type make[3]: * [rokko/CMakeFiles/rokko.dir/string.F90.o] Error 1 make[2]: * [rokko/CMakeFiles/rokko.dir/string.F90.o.provides] Error 2 make[1]: * [rokko/CMakeFiles/rokko.dir/all] Error 2 make: * [all] Error 2