Ich habe eine große, gemischte C/Fortran, Code-Basis, derzeit kompiliert mit den Intel-Tools unter Windows. Ich wurde gebeten, es unter Linux in die GNU-Tools zu portieren. Mehr oder weniger zufällig habe ich Version 4.8 ausgewählt. GNU Fortran und C Interoperabilität
Wenn eine C-Funktion aus Fortran aufgerufen wird, sieht die Interoperabilität oft wie folgt aus:
// 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
Der Intel Fortran Compiler immer in Großbuchstaben Symbole erzeugt, so dass dies funktioniert. Aber der GNU Fortran-Compiler erzeugt immer Kleinbuchstaben und daher gibt es einen Linker-Fehler.
Der GNU Fortran-Compiler hatte eine Option namens -fcase-upper
, mit der es Großbuchstaben-Symbole erzeugen konnte, aber es schien zu konfigurierbar zu sein und es wurde entfernt (ich bin mir nicht ganz sicher wann).
Es ist möglich, die ISO_C_BINDING
Einrichtung zu verwenden, um den Compiler zu zwingen, Groß- und Kleinschreibung Namen zu generieren:
program test
interface
subroutine printstr(str) bind(C, name='PRINTSTR')
character :: str(*)
end subroutine
end interface
call printstr("Hello, world.")
end
Dieser den Linker Fehler behebt, aber es ändert sich wie String-Parameter behandelt werden; Der Parameter length wird nicht mehr bereitgestellt. Um diese Methode zu verwenden, müsste ich nicht nur Interface-Definitionen für jede Funktion hinzufügen, die derzeit auf diese Weise funktioniert, sondern ich müsste auch ändern, wie Strings bei jedem Aufruf einer solchen Funktion gehandhabt werden, und sicherstellen, dass alle Strings funktionieren sind null-terminiert.
Ich könnte gehen und alle diese Funktionen in Kleinbuchstaben machen, aber natürlich der Intel-Compiler generiert immer noch Großbuchstaben-Symbole, so dass würde die bestehende Build zu brechen.
Da es ~ 2000 solche Funktionen gibt, scheint das eine unmögliche Menge an Arbeit. Meine Frage lautet also: Wie kann ich die Verbindungsfehler auflösen, ohne die Semantik des Funktionsaufrufs zu ändern und ohne den vorhandenen Build mit den Intel-Compilern zu unterbrechen?
Ich fürchte, ein etwas größeres Problem, das Sie haben werden, ist, dass Intel die Länge als 'size_t 'übergibt, während GFortran' int' verwendet. Bei 32-Bit ist das in Ordnung, bricht aber bei 64-Bit-Systemen, die mehr als einen String gleichzeitig passieren, furchtbar ein und wird nicht einmal vom Linker abgefangen. –
Ich denke, rein durch viel Glück komme ich damit durch. Der Intel-Build ist 32-Bit. – Tom
Ich denke (möglicherweise) der Compiler, der '-Fase-Upper' hatte, war G95, nicht GFortran (das ist jetzt der offizielle GNU Fortran Compiler). AFAIK G95 wird immer noch entwickelt, wenn auch langsamer als GFortran, aber wenn Ihre Codebasis reines F77/F95 ist und keine hochmodernen F2003/F2008-Funktionen verwendet, kann es sich lohnen, etwas genauer zu betrachten. –