c++ - 如何将字符串数组从 C 和 Fortran 传递给 Fortran?

标签 c++ c fortran fortran-iso-c-binding

我正在尝试将字符串数组从 C 传递到 Fortran 子例程,以及从 Fortran 传递到同一个 Fortran 子例程。我成功地从 C 和 Fortran 传递了单个字符串(即一维字符数组)。但是,我在处理字符串数组时遇到了问题。我在 Fortran 端使用 ISO C 绑定(bind),理想情况下我希望这在调用端尽可能无缝。

我已经阅读了一些相关的问题和答案。有些(即 thisthis )只是“使用 ISO C”,没有进一步的细节,这没有多大帮助。 This answer非常有帮助(类似于 a different question 的答案),但仅适用于单个字符串,其中似乎在单个 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;
}

还有一个类似的 Fortran 例程:

program main
  implicit none
  call print_hi_array( (/"asdf", "ghji", "zxcv"/) )
end program

到目前为止,这是我在接收端所拥有的:

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

这适用于 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   

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

asdfghjizxcv@O,B�@(P,B�]B]6(P,B�@ .......

这个方法好像没有c_null_char

那么,我如何编写 Fortran 子例程来接收来自 C 和 Fortran 的字符串数组?

最佳答案

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

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

可以这样在数组构造函数中定义字符串的长度:

[character(255) :: "a","ab","abc"]

关于c++ - 如何将字符串数组从 C 和 Fortran 传递给 Fortran?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13869528/

相关文章:

c++ - 如何使用playsound()播放用户指定的声音文件?

c - 创建只有一个字段的结构体的目的是什么

c - bool - 255 值

c - 如何在C和Linux中打印黑桃、红心、方 block 等?

loops - 检查变量是否已使用 Fortran 77 声明?

vim - 为 pFUnit 测试框架扩展 vim Fortran 语法文件

c++ - 为什么在 .cpp 中使用 #include<.hpp>,而不是在 .hpp 中使用 <.cpp>?

c++ - STL 模板容器的 GDB 中的 "Cannot evaluate function -- may be in-lined"错误

c++ - 将 Glut 鼠标坐标转换为 opengl

fortran - 在 Fortran 过程中可以有隐式种类