t-sakashita / rokko

Integrated Interface for libraries of eigenvalue decomposition
Boost Software License 1.0
10 stars 2 forks source link

gcc 4.4 で rokko/string.F90 のコンパイルに失敗 #187

Closed wistaria closed 4 years ago

wistaria commented 9 years ago

$ 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:

 character(len=:), allocatable :: str
               1

Error: Syntax error in CHARACTER declaration at (1) /home/wistaria/development/rokko/rokko/string.F90:30.18:

character(len=:), allocatable, intent(out) :: val
              1

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

t-sakashita commented 9 years ago

エラーが出ているのは、動的にサイズを指定できる文字列の宣言部分です。 (Fortranも文字列は、character型の配列ではなく、1個のスカラー。)

そのため、gfortran4.8以前のものは、切り捨てたいです。。。

wistaria commented 9 years ago

京やFX10の frtpx では Fortran2003 はサポートされていますか?そうであれば Fortran2003 以前は切り捨てて良いと思います。

CMake で Fortran2003 がサポートされているかどうかチェックして、サポートされていない場合には BUILD_Fortran_BINDING を自動的に OFF にすることはできますか?

t-sakashita commented 9 years ago

はい、できると思います。

対策:

t-sakashita commented 4 years ago

https://stackoverflow.com/questions/35153637/how-to-get-command-line-arguments-of-unknown-length-in-fortran

t-sakashita commented 4 years ago

以下はコンパイルは通るが、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
t-sakashita commented 4 years ago

ルーチン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
t-sakashita commented 4 years ago

今や、文字列のdeferred lengthは、全てのFortranコンパイラ実装されている。 この使用をデフォルトとした。

094d6bb56babe7c4800b67159d2473a4aaafca31

t-sakashita commented 4 years ago

変更案:

rokko_serial_dense_ev_default_solverは、subroutineからfunctionに変更する。 戻り値型は、len=とする。 すると、左辺型が、len=とlen=:のどちらの場合も使えるはず。 len=:の場合は、automatically allocating suitable sizeとなるため。

t-sakashita commented 4 years ago

std::stringの.size()を使えば、末尾のヌル文字を検出しなくても良くなる。 この場合、Fortranバインディング用のCラッパー関数が必要となる。(Cバインディングでは使えない関数である。)

t-sakashita commented 4 years ago

"Modern Fortran Explained (5th edition)"のp.109 Sec. 6.7 "Automatic reallocation"

t-sakashita commented 4 years ago

https://qiita.com/sage-git/items/7f1d5723b0c0d32c60d5

t-sakashita commented 4 years ago

https://stackoverflow.com/questions/20365293/converting-a-variable-length-c-string-to-fortran-string-in-visual-studio

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

t-sakashita commented 4 years ago

"Modern Fortran Explained (5th edition)"のp.410 Sec.21.6.5 Allocatable objects

以下は、Fortran 2008の機能なので、まだ使えない。

t-sakashita commented 4 years ago
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
t-sakashita commented 4 years ago

a8d694c1bfad2da59852d9377c4a5df5b57dce93