我遇到了在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组合很难。
答案 0 :(得分:4)
我相信你要找的答案就在这里:
Arrays of strings in fortran-C bridges using iso_c_binding
基本上,fortran“知道”字符串的长度但不知道C,所以你必须通过将fortran长度传输到C然后在C代码中适当地做出反应来让C代码知道。
下面的这个问题从“纯粹的”Fortran POV中探讨了这个问题,并给出了各种答案中的一些见解:
Fortran to C , effect of trim on space allocated to string
请记住,编译器可能会利用一些未定义或特定于实现的差异来解释观察到的各种行为。
另外,我只是假设sizeof
给出了字符串的大小,我才意识到你犯了一个错误。它给出了指针的大小。所以sizeof(name)/sizeof(name[0])
是一个常量,给出char
的大小,它本身是C中8个字节的常量。sizeof(name)
给出了char指针的大小,sizeof(name[0])
给出了char的大小。结果是常数8。
答案 1 :(得分:2)
这里有几个问题。
sizeof(name)
返回名为name的指针的大小。我认为你是64位平台 - 所以你总是看到8。
C经常要求字符串长度由尾随的空前哨字符决定。缺少这个角色会产生奇怪的结果。如果没有更多信息,我们无法确定这是否是一个问题。
Fortran编译器在字符变量长度方面的传递约定不同 - 它可能在指向字符数据的指针后立即附加,或者附加到其他参数的末尾。过程与BIND(C)属性的互操作性规则消除了传递此长度的要求,因为可互操作的字符变量只能是长度为1。我们无法确定这是否是一个问题,因为您没有在Fortran端显示子例程调用的接口块。
所以...决定你如何管理C端的字符串长度(固定长度?终止null?单独传递长度?),适当调整Fortran调用并使用BIND(C)向Fortran端添加接口块)。