3

我在 Fortran 和 C 之间传递字符串时遇到问题。

Fortran 子例程调用如下所示:

CALL MMEINITWRAPPER(TRIM(ADJUSTL(PRMTOP)), 0, SALTCON, RGBMAX, CUT)

与此一起使用的 C 具有签名:

int mmeinitwrapper_(char *name,
                    int *igb,
                    REAL_T *saltcon,
                    REAL_T *rgbmax1,
                    REAL_T *cutoff1)

我在不同的地方放了一些打印语句,一切正常,直到我用 ifort 编译。在这种情况下,输出如下所示:

  Topology file name:
 coords.prmtop                                                                  
   coords.prmtop
 Topology file name length:          81          13
length in C: 8 
read argument: coords.prmtop��* 
Reading parm file (coords.prmtop��*)
coords.prmtop��*, coords.prmtop��*.Z: does not exist
Cannot read parm file coords.prmtop��*

使用波特兰编译器:

  Topology file name:
 coords.prmtop                                                                    
 coords.prmtop
 Topology file name length:           81           13
length in C: 8 
read argument: coords.prmtop 
Reading parm file (coords.prmtop)

第一组中的长度来自未修剪/未调整字符串的 Fortran,然后是修剪/调整字符串。C 中的长度从sizeof(name)/sizeof(name[0]).

它似乎传递了一段太长的内存,在随后的运行中,你会得到不同长度的坏东西(尽管 C 中报告的长度总是 8)。

有没有人有任何想法?很难让 gdb 与 Fortran/C 组合很好地配合使用。

4

2 回答 2

5

我相信您正在寻找的答案在这里:

使用 iso_c_binding 的 fortran-C 桥中的字符串数组

基本上,fortran“知道”字符串的长度,但不知道 C,因此您必须通过将 fortran 长度传输到 C,然后在 C 代码中做出适当反应,以某种方式让 C 代码知道。

下面的这个问题从“纯”fortran POV 探讨了这个问题,并对给出的各种答案有一些见解:

Fortran 到 C ,修剪对分配给字符串的空间的影响

请记住,编译器可能会利用一些未定义或特定于实现的差异来解释观察到的各种行为。

另外,我刚刚意识到您通过假设sizeof给出字符串的大小而犯了一个错误。它给出了指针的大小。sizeof(name)/sizeof(name[0])一个常量也给出了 a 的大小,它char本身在 C 中是一个 8 字节的常量。sizeof(name)给出了 char 指针sizeof(name[0])的大小并给出了 char 的大小。结果是常数 8。

于 2013-11-11T19:26:22.343 回答
2

这里有几个问题。

  • sizeof(name)在 C 中返回名为 name 的指针的大小。我认为您在 64 位平台上 - 因此您总是看到 8。

  • C 通常期望字符串长度由尾随的空标记字符确定。缺少该字符会产生奇怪的结果。如果没有更多信息,我们无法确定这是否是一个问题。

  • Fortran 编译器在字符变量长度的传递约定上有所不同——它可能是紧跟在指向字符数据的指针之后的附加内容,或者附加到其他参数的末尾。关于具有 BIND(C) 属性的过程的互操作性的规则删除了传递此长度的要求,因为可互操作的字符变量的长度只能为 1。我们不能确定这是否是一个问题,因为您没有为 Fortran 端的子例程调用显示接口块。

所以...决定如何在 C 端管理字符串长度(固定长度?终止 null?单独传递的长度?),适当调整 Fortran 调用并使用 BIND(C) 将接口块添加到 Fortran 端。

于 2013-11-11T19:45:13.587 回答