将一个C字符串数组传递给Fortran(iso_c_binding)

ale*_*rba 5 c string fortran fortran-iso-c-binding

如何将C strings(char* cstrings[])数组传递给Fortran子例程?

问题使用iso_c_binding的fortran-C桥接器中的字符串数组肯定是相关的,但答案似乎不正确,甚至不能用GNU Fortran编译.

我目前正在为Fortran代码开发一个C接口,我预计iso_c_binding(我之前使用过的)会让这件事变得轻而易举.到目前为止C字符串数组没有运气......

Fortran子例程应该将一个字符串数组作为参数.在普通的Fortran中,我会写如下内容:

subroutine print_fstring_array(fstring)

  implicit none

  character(len=*), dimension(:), intent(in) :: fstring
  integer                                    :: i

  do i = 1, size(fstring)
    write(*,*) trim(fstring(i))
  end do

end subroutine print_fstring_array
Run Code Online (Sandbox Code Playgroud)

将单个C字符串传递给Fortran的一种方法是作为C指针(c_ptr)(我知道,我也可以使用一个数组character(kind=c_char))

subroutine print_cstring(cstring) bind(C)

  use iso_c_binding, only: c_ptr, c_f_pointer, c_loc, c_null_char
  implicit none

  type(c_ptr), target, intent(in) :: cstring
  character(len=1024), pointer    :: fstring
  integer                         :: slen

  call c_f_pointer(c_loc(cstring), fstring)
  slen = index(fstring, c_null_char) - 1
  write(*,*) fstring(1:slen)

end subroutine print_cstring
Run Code Online (Sandbox Code Playgroud)

所以,我假设一个阵列c_ptr是个好主意

subroutine print_cstring_array(n, cstring) bind(C)

  use iso_c_binding, only: c_ptr, c_int, c_f_pointer, c_loc, c_null_char
  implicit none

  integer(kind=c_int),               intent(in) :: n
  type(c_ptr), dimension(n), target, intent(in) :: cstring
  character(len=1024), pointer                  :: fstr
  integer                                       :: slen, i

  do i = 1, n
    call c_f_pointer(c_loc(cstring(i)), fstring)
    slen = index(fstring, c_null_char) - 1
    write(*,*) fstring(1:slen)
  end do

end subroutine print_cstring_array
Run Code Online (Sandbox Code Playgroud)

但这会产生分段错误.

最后一个例子的C代码是

# include "stdio.h"
# include "fstring.h"

void main(void) {
  char* cstring[] = { "abc", "def", "ghi", "jkl" };
  int n = 4;
  print_cstring_array(&n, cstring);
}
Run Code Online (Sandbox Code Playgroud)

并且头文件的内容fstring.h很简单:

void print_cstring_array(int* n, char* cstring[]);
Run Code Online (Sandbox Code Playgroud)

我的目标是GNU Fortran和英特尔Fortran,并使用GNU Fortran测试了上述内容.字符串长度是固定的(在上例中为3),以防这种情况简化了解决方案.但是,阵列的尺寸可以变化.

任何指针(甚至C指针)都将非常感激.

Vla*_*r F 6

问题中代码中最大的问题是您使用c_f_pointer(c_loc(cstring),而不是c_f_pointer(cstring,.

这对我有用:

subroutine print_cstring_array(n, cstring) bind(C)

  use iso_c_binding, only: c_ptr, c_int, c_f_pointer, c_loc, c_null_char
  implicit none

  integer(kind=c_int),               intent(in) :: n
  type(c_ptr), dimension(n), target, intent(in) :: cstring
  character, pointer                            :: fstring(:)
  integer                                       :: slen, i

  do i = 1, n
    call c_f_pointer(cstring(i), fstring, [4])
    write(*,*) fstring
  end do

end subroutine print_cstring_array



# include "stdio.h"

void print_cstring_array(int* n, char* cstring[]);

void main(void) {
  char* cstring[] = { "abc", "def", "ghi", "jkl" };
  int n = 4;
  print_cstring_array(&n, cstring);
}
Run Code Online (Sandbox Code Playgroud)

  • @alexurba不,没关系.我将`type(C_PTR)`传递给`c_f_pointer`,它的类型正确.你的参考证实了,虽然我非常了解'c_f_pointer`. (2认同)