在Fortran和C之间传递字符串

我在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  * 

使用Portland编译器:

  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组合很好地配合使用。

我相信你要找的答案就在这里:

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

基本上,fortran“知道”字符串的长度但不知道C,所以你必须通过将fortran长度传输到C然后在C代码中适当地做出反应来让C代码知道。

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

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

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

此外,我只是通过假设sizeof给出字符串的大小来意识到你犯了一个错误。 它给出了指针的大小。 因此sizeof(name)/sizeof(name[0])是一个常量,给出一个char的大小,它本身是C中8个字节的常量sizeof(name)给出了char指针和sizeof(name[0])给出了char的大小。 结果是常数8。

这里有几个问题。

  • C中的sizeof(name)返回名为name的指针的大小。 我认为你是64位平台 – 所以你总是看到8。

  • C经常要求字符串长度由尾随的空前哨字符确定。 缺少这个角色会产生奇怪的结果。 如果没有更多信息,我们无法确定这是否是一个问题。

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

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