0

create_test_sourcelist を使用して CTest で実行したいいくつかの Fortran テストがあります。これは C または C++ でドライバを作成するユーティリティで、fortran テスト ルーチンを呼び出して署名を期待します。

int fortname(int argv, char** argc)

おそらく iso_c_bindings を使用して、この署名をインターフェイスする正しい方法を誰かが説明できますか?これらはかなり標準になっていると理解しています。私を傷つけているのは char** だと思います-整数引数の例はたくさんあります。

ありがとう!

4

2 に答える 2

3

C プログラムの main 関数のコンテキストにおける argc と argv の意味が当てはまると仮定すると、次のようなことができます。

! Default binding label is already lower case, but for clarity 
! it is good practice to specify the binding label explicitly.
function fortname(argc, argv) bind(c, name='fortname')
  use, intrinsic :: iso_c_binding, only: c_int, c_ptr           
  implicit none          
  !----
  ! Note C std allows argc == 0
  integer(c_int), intent(in), value :: argc
  ! Lower bound set to match C convention where element 0 probably 
  ! is name of program.  May be zero size.
  type(c_ptr), intent(in) :: argv(0:argc-1)
  ! Function result.
  integer(c_int) :: fortname

これらの引数を Fortran で使いやすいものに変換するには (さらに、Fortran プロセッサが Fortran 2003 標準の適用可能なすべての部分をサポートしていると仮定し、現在、少なくとも 1 つの一般的に使用されているプロセッサでは遅延長文字コンポーネントがサポートされていないことに注意してください)あなたはそれからすることができます...

  !----
  ! Name of the program.
  character(:), allocatable :: prog_name      
  ! Type to use for arrays of pointers to variable length strings.
  type :: string
    character(:), allocatable :: item
  end type string
  ! Our arguments.  May be zero size.
  type(string) :: arguments(argc-1)      
  integer :: i   ! argument index.      
  !****
  if (argc > 0) then   ! argv has something useful
    ! make program name accessible to fortran code.        
    call c_f_string(argv(0), prog_name)
    ! make arguments accessible to fortran code.
    do i = 1, size(arguments)
      call c_f_string(argv(i), arguments(i)%item)
    end do
  else  ! no useful information provided in argv
    prog_name = ''
  end if

  ! Work with arguments%item and prog_name...      
  print "(A)", prog_name
  do i = 1, size(arguments) ; print "(A)", arguments(i)%item ; end do

  fortname = 0      
contains
  ! Copy a null terminated C string (specified via a non-null c_ptr) to an 
  ! allocatable deferred length default character variable.
  subroutine c_f_string(c_string, f_string)
    use, intrinsic :: iso_c_binding, only: c_char, c_null_char, c_f_pointer
    !----
    type(c_ptr), intent(in) :: c_string
    character(:), intent(out), allocatable :: f_string
    !----
    ! Array for accessing string pointed at by C pointer 
    character(kind=c_char), pointer :: string_ptr(:)
    integer :: i    ! string index
    interface
      ! Steal std C library function rather than writing our own.
      function strlen(s) bind(c, name='strlen')
        use, intrinsic :: iso_c_binding, only: c_ptr, c_size_t
        implicit none
        !----
        type(c_ptr), intent(in), value :: s
        integer(c_size_t) :: strlen
      end function strlen
    end interface
    !****
    ! Map C pointer to fortran character array
    call c_f_pointer(c_string, string_ptr, [strlen(c_string)])
    ! Allocate fortran character variable to the c string's length
    allocate(character(size(string_ptr)) :: f_string)
    ! Copy across (with possible kind conversion) characters
    forall (i = 1:size(string_ptr)) f_string(i:i) = string_ptr(i)
  end subroutine c_f_string      
end function fortname
于 2012-07-12T00:46:53.723 に答える