2014-10-15 17 views
5

Mam dużą, mieszaną C/Fortran, bazę kodu, aktualnie kompilowaną przy użyciu narzędzi Intel w systemie Windows. Zostałem poproszony o przeniesienie go na narzędzia GNU, w systemie Linux. Mniej więcej losowo wybrałem wersję 4.8.Współdziałanie GNU Fortran i C

Jeżeli funkcja C jest wywoływana z Fortran, interoperacyjność często wygląda tak:

// 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 

Intel Fortran kompilator zawsze generuje symbole wielkich liter, tak to działa prawidłowo. Ale kompilator GNU Fortran zawsze generuje małe litery, a więc występuje błąd linkera.

Kompilator GNU Fortran miał opcję o nazwie -fcase-upper, która powodowała generowanie wielkich liter, ale wydaje się, że była ona zbyt konfigurowalna dla dobra wszystkich osób i została usunięta (nie jestem dokładnie pewien kiedy).

Jest możliwe, aby skorzystać z możliwości ISO_C_BINDING zmusić kompilator do wygenerowania wielkości liter nazwy:

program test 
interface 
subroutine printstr(str) bind(C, name='PRINTSTR') 
character :: str(*) 
end subroutine 
end interface 

call printstr("Hello, world.") 
end 

to rozwiąże błąd linkera ale zmienia jak parametry łańcuchowe są obsługiwane; parametr długości nie jest już dostępny. Aby użyć tej metody, nie musiałbym tylko dodawać definicji interfejsu dla każdej funkcji, która obecnie działa w ten sposób, ale musiałbym również zmienić sposób obsługi ciągów w każdym wywołaniu takiej funkcji, upewniając się, że wszystkie ciągi są zakończone znakiem NUL.

Mógłbym przejść przez wszystkie takie funkcje małymi literami, ale oczywiście kompilator Intela nadal generuje wielkie litery, aby złamać istniejącą kompilację.

Ponieważ istnieje ~ 2000 takich funkcji, wydaje się, że niewykonalna ilość pracy. Tak, moje pytanie jest następujące: Jak mogę rozwiązać błędy łącza bez zmiany semantyki funkcji połączenia i bez łamania istniejącej kompilacji przy użyciu kompilatorów Intel?

+0

Obawiam się, że raczej większy problem będzie polegał na tym, że Intel podaje długość jako 'size_t', podczas gdy GFortran używa' int'. To jest w porządku na 32-bitowych, ale strasznie się psuje 64-bitowych systemów przechodzących więcej niż jeden ciąg na raz, a nawet nie zostanie złapany przez linker. –

+0

Myślę, że, szczęśliwie, ucieknę z tym. Kompilacja Intela jest 32-bitowa. – Tom

+0

Myślę (prawdopodobnie) kompilator, który miał '-fcase-upper' był g95, a nie GFortran (który jest teraz oficjalnym kompilatorem GNU Fortran). AFAIK g95 jest nadal rozwijany, choć w wolniejszym tempie niż GFortran, ale jeśli twoja baza kodów jest czysta F77/F95 i nie używa najnowocześniejszych funkcji F2003/F2008, może warto się przyjrzeć? –

Odpowiedz

2

Aby rozwiązać problem z linkerem, możesz zrobić to w inny sposób. Użyj opcji kompilatora Intel names, aby konwertować nazwy zewnętrzne na małe litery, aby pasowały do ​​domyślnej opcji GNU Fortran. I konwertować nazwy w na małe też:

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

Osobiście polecam korzystania -funderscoring i Intela /assume:underscore odróżnić funkcje, które są przeznaczone do współdziałania.