如何将字符串数组从C和Fortran传递到Fortran?

Eli*_*sey 5 c c++ fortran fortran-iso-c-binding

我试图将字符串数组从C传递到Fortran子例程,以及从Fortran传递到相同的Fortran子例程。我已经成功地从C和Fortran中成功传递了单个字符串(即1D字符数组)。但是,我在处理字符串数组时遇到了麻烦。我在Fortran端使用ISO C绑定,理想情况下,我希望在调用端尽可能做到无缝。

我已经阅读了一些相关的问题和答案。有些(即thisthis)只是“使用ISO C”而没有更多细节,这并没有太大帮助。这个答案非常有帮助(对不同问题的类似答案),但是仅适用于单个字符串,其中似乎在单个Fortran字符串中识别了c_null_char。如果没有两个单独的例程,我无法弄清楚数组情况该怎么办。

我现在有一个C例程,我想从其中传递字符串数组(string):

#include <iostream>

extern "C" void print_hi_array(char input_string[][255]);

using namespace std;

int main() {

  char string[3][255] = {"asdf","ghji","zxcv"};   
  print_hi_array(string);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

并且,一个类似的Fortran例程:

program main
  implicit none
  call print_hi_array( (/"asdf", "ghji", "zxcv"/) )
end program
Run Code Online (Sandbox Code Playgroud)

到目前为止,这是我对接收端的要求:

subroutine print_hi_array(input_string) bind(C)
  use iso_c_binding, only: C_CHAR, c_null_char

  implicit none

  character (kind=c_char, len=1), dimension (3,255), intent (in) :: input_string
  character (len=255), dimension (3) :: regular_string
  character (len=255) :: dummy_string
  integer :: i,j,k

  write (*,*) input_string

  do j = 1 , 3
    dummy_string(:) = c_null_char
    k = 1
    do i = 1 + (j-1)*255, j*255,1
      if (input_string(i) .ne.  c_null_char) then
        write (*,*) "i ",i,j, input_string(i)
        dummy_string(k:k) = input_string(i)
      endif
    k = k +1
    enddo
    regular_string(j) = dummy_string
  enddo

  write (*,*) regular_string

end subroutine print_hi_array
Run Code Online (Sandbox Code Playgroud)

这适用于C函数;我得到以下输出:

 asdfghjizxcv
 j=           1
 i            1           1 a
 i            2           1 s
 i            3           1 d
 i            4           1 f
 j=           2
 i          256           2 g
 i          257           2 h
 i          258           2 j
 i          259           2 i
 j=           3
 i          511           3 z
 i          512           3 x
 i          513           3 c
 i          514           3 v
 asdf   ghji   zxcv   
Run Code Online (Sandbox Code Playgroud)

但是,当通过Fortran完成时,我会胡说八道:

asdfghjizxcv@O,B?@(P,B?]B]6(P,B?@ .......
Run Code Online (Sandbox Code Playgroud)

似乎没有c_null_char这种方法。

因此,如何编写一个Fortran子例程以从C和Fortran接收字符串数组?

Vla*_*r F 5

如果声明的字符串长于其存储的文本,则Fortran将使用空格来填充字符串的其余部分。它不是零定界的,声明的长度存储在一个隐藏变量中。它不包含c null char,因此您正在读取一些垃圾(缓冲区溢出)。标准未定义tlit打印\ 000字符串时Fortran应该打印的内容,具体取决于实现。

特别是,您还将一个维度为3的character(4)数组传递给期望更多数据的子例程(255个字符,尽管我不确定索引顺序)。仅传递指针,因此我认为无法检查。

可以通过以下方式在数组构造函数中定义字符串的长度:

[character(255) :: "a","ab","abc"]
Run Code Online (Sandbox Code Playgroud)