我有一个大型的混合C / Fortran代码库,目前使用Windows上的英特尔工具进行编译。我被要求将它移植到Linux上的GNU工具。或多或少随意,我选择了4.8版本。
从Fortran调用C函数时,互操作性通常如下所示:
// C code:
void PRINTSTR(char *str, size_t len) {
for(int ii = 0; ii < len; ii++) {
putchar(str[ii]);
}
putchar('\n');
}
!Fortran code:
program test
implicit none
call printstr("Hello, world.")
end
英特尔Fortran编译器始终生成大写符号,因此可以正常工作。但是GNU Fortran编译器总是生成小写符号,因此存在链接器错误。
GNU Fortran编译器曾经有一个名为-fcase-upper
的选项,它使它生成大写符号,但似乎这对于每个人的好而言都是可配置的并且已被删除(我不确定何时)。
可以使用ISO_C_BINDING
工具强制编译器生成区分大小写的名称:
program test
interface
subroutine printstr(str) bind(C, name='PRINTSTR')
character :: str(*)
end subroutine
end interface
call printstr("Hello, world.")
end
这解决了链接器错误,但它改变了字符串参数的处理方式;不再提供length参数。因此,要使用此方法,我不仅必须为当前以这种方式工作的每个函数添加接口定义,而且还必须在每次调用此类函数时更改字符串的处理方式,确保所有字符串是以空值终止的。
我可以通过小写来完成所有这些函数,但当然英特尔编译器仍会生成大写符号,这样就会破坏现有的构建。
由于有大约2,000个这样的功能,这似乎是不可行的工作量。所以,我的问题是:如何在不改变函数调用语义的情况下解决链接错误,并且不使用英特尔编译器破坏现有构建?
答案 0 :(得分:2)
要解决链接器错误,您可以通过其他方式执行此操作。使用英特尔编译器选项names将外部名称转换为小写以匹配默认的GNU Fortran选项。并将c中的名称转换为小写:
void printstr(char *str, size_t len) {...}
我个人建议使用-funderscoring
和英特尔/assume:underscore
来区分旨在实现互操作性的功能。
// C code:
void printstr_(char *str, size_t len) {...}
!Fortran code:
program test
implicit none
call printstr("Hello, world.")
end