C++ GNU Fortran和C的互操作性

C++ GNU Fortran和C的互操作性,c++,c,fortran,gfortran,language-interoperability,C++,C,Fortran,Gfortran,Language Interoperability,我有一个大型的混合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'); }

我有一个大型的混合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
这解决了链接器错误,但改变了字符串参数的处理方式;不再提供长度参数。因此,要使用此方法,我不仅需要为当前以这种方式工作的每个函数添加接口定义,还必须更改在对此类函数的每次调用中处理字符串的方式,确保所有字符串都以null结尾

我可以把所有这些函数都改成小写,但当然英特尔编译器仍然会生成大写符号,这将破坏现有的构建


由于大约有2000个这样的函数,这似乎是一个不可行的工作量。因此,我的问题是:如何在不更改函数调用语义和不破坏使用英特尔编译器的现有生成的情况下解决链接错误?

要解决链接器错误,可以采用其他方法。使用“英特尔编译器”选项将外部名称转换为小写,以匹配默认的GNU Fortran选项。并将名称转换为小写:

void printstr(char *str, size_t len) {...}
就我个人而言,我建议使用
-funderscoring
和英特尔的
/aspect:subline
来区分用于互操作性的函数

// C code:
void printstr_(char *str, size_t len) {...}

!Fortran code:
program test
implicit none
call printstr("Hello, world.")
end

恐怕你会遇到一个更大的问题,Intel将长度作为
size\u t
传递,而GFortran使用
int
。这在32位上很好,但在64位系统上一次传递多个字符串时会出现可怕的中断,甚至不会被链接器捕捉到。我认为,纯粹是运气好,我侥幸逃脱了这个问题。英特尔版本是32位的。我认为(可能)拥有
-fcase-upper
的编译器是g95,而不是GFortran(现在是官方的GNU Fortran编译器)。AFAIK g95仍在开发中,尽管开发速度比GFortran慢,但如果您的代码库是纯F77/F95,并且没有使用最先进的F2003/F2008功能,那么可能值得研究一下?这些确实是从Fortran到C的~2000个不同的函数接口吗?或者这些调用只是对几个具有不同参数的函数的调用?在后一种情况下,您只需编写一些包装器,为您添加
C_NULL_CHAR
。仔细看,我的许多(数千个)链接器问题与此无关。从Fortran到C有244个不同的函数接口,称为410次。所以现在不是2000年,但要解决所有问题也不是一件小事。
// C code:
void printstr_(char *str, size_t len) {...}

!Fortran code:
program test
implicit none
call printstr("Hello, world.")
end