在Fortran和C之间传递字符串 [英] Passing string between Fortran and 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编译。在这种情况下,输出如下所示:
拓扑文件名称:
coords.prmtop
coords .prmtop
拓扑文件名称长度:81 13
C中的长度:8
读取参数:coords.prmtop *
读取parm文件(coords.prmtop *)
coords.prmtop *,coords.prmtop * .Z:不存在
无法读取parm文件coords.prmtop *
使用波特兰编译器:
拓扑文件名称:
coords.prmtop
coords.prmtop
拓扑文件名称长度:81 13
C中的长度:8
读取参数:coords.prmtop
读取parm文件(coords.prmtop)
第一组中的长度来自未修改/未调整字符串的Fortran,然后修剪/调整str ING。 C中的长度是从 sizeof(name)/ sizeof(name [0])
。
要传递一段太长的内存,并在随后的运行中得到不同长度的坏东西(尽管C中报告的长度始终为8)。
有没有人有什么想法?
我相信你要找的答案就在这里:
使用iso_c_binding 在fortran-C桥中的字符串数组
基本上,fortran知道字符串的长度但不是C你必须让C代码以某种方式知道,将fortran长度传输给C,然后在C代码中适当地作出反应。
下面的这个问题从一个纯粹的fortran POV探索这个问题,并给出了各种答案中的一些见解:
请记住,编译器可能会利用一些未定义的或特定于实现的差异来解释不同的观察行为。
另外,我通过假定 sizeof
给出了字符串的大小,从而意识到你犯了一个错误。它给出指针的大小。所以 sizeof(name)/ sizeof(name [0])
是一个常数,它给出了一个 char
的大小本身是C中8个字节的常量。 sizeof(name)
给出了char指针的大小, sizeof(name [0])
给出了字符的大小。结果是一个常数8。
I have a problem with passing strings between Fortran and C.
The Fortran subroutine call looks like this:
CALL MMEINITWRAPPER(TRIM(ADJUSTL(PRMTOP)), 0, SALTCON, RGBMAX, CUT)
The C which works with this has the signature:
int mmeinitwrapper_(char *name,
int *igb,
REAL_T *saltcon,
REAL_T *rgbmax1,
REAL_T *cutoff1)
I put some print statements in various places and everything works just fine, until I compile with ifort. In that case, the output looks like this:
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��*
With the Portland compiler:
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)
The lengths in the first set are from Fortran of the untrimmed/unadjusted string and then the trimmed/adjusted string. The length in C is from sizeof(name)/sizeof(name[0])
.
It seems to be passing a section of memory that's too long and in subsequent runs you get different lengths of bad stuff written (though the reported length in C is always 8).
Does anyone have any ideas? It's difficult getting gdb to play nicely with the Fortran/C combination.
I believe the answer you're looking for is here:
Arrays of strings in fortran-C bridges using iso_c_binding
Basically, fortran "knows" the length of a string but not C so you have to let the C code know somehow by transmitting the fortran length to C and then reacting appropriately in the C code.
This question below explore this issue from a "pure" fortran POV with some insights in the various answers given:
Fortran to C , effect of trim on space allocated to string
And bear in mind that the compilers might exploit some undefined or implementation-specific differences to explain the varied observed behavior.
Also, I just realized you make a mistake by assuming that sizeof
gives the size of the string. It gives the size of the pointer. So sizeof(name)/sizeof(name[0])
is a constant giving the size of a char
which itself is a constant of 8 bytes in C. sizeof(name)
gives the size of a char pointer and sizeof(name[0])
gives the size of a char. The result is a constant 8.
这篇关于在Fortran和C之间传递字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!