2014-10-15 12 views
5

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?

+0

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. –

+0

Ich denke, rein durch viel Glück komme ich damit durch. Der Intel-Build ist 32-Bit. – Tom

+0

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. –

Antwort

2

Um den Linker-Fehler zu lösen, können Sie es anders herum tun. Verwenden Sie die Intel-Compileroption names, um externe Namen in Kleinbuchstaben umzuwandeln, damit sie der standardmäßigen GNU Fortran-Option entsprechen. Und konvertieren Name in auch in Kleinbuchstaben:

void printstr(char *str, size_t len) {...} 

Persönlich würde ich empfehlen die Verwendung von -funderscoring und Intels /assume:underscore Funktionen zu unterscheiden, die für die Interoperabilität vorgesehen sind.