В UNIX системах языки Си и Фортран могут использоваться вместе, так как между этими языками возможны прямые вызовы функций. При этом, правда, необходимо тщательно учитывать совместимость типов передаваемых аргументов. Обычно соответствие между типами в Си и Фортране можно представить так:
signed char INTEGER*1
short INTEGER*2
int INTEGER
long INTEGER*4
float REAL
double DOUBLE PRECISION
void sub_ SUBROUTINE SUB()
float fun_() REAL FUNCTION FUN
Также следует помнить о следующем:
- в Фортране аргументы в функции всегда передаются ссылками;
- В Си массивы передаются через адрес;
- Порядок индексации многомерных массивов различен для Си и Фортрана - в Си элементы массива располагаются построчно, в Фортране - по столбцам;
- Имена функций в Фортране имеют в своем конце "скрытый" знак подчеркивания '_' (его нет в исходном тексте, но он добавляется компилятором), поэтому, если некая фунция вызывается из Фортрана как fun(), то эта же функция из Си вызывается как fun_() ;
- В языке Си длина строки определяется положением нулевого байта, в Фортране же строки имеют фиксированную длину. Поэтому при передаче строки из Си кода в Фортран необходимо передавать также ее длину. В случае же передачи строки из Фортран кода в Си необходимо добавить нуль в конец строки;
Файл cCode1.c:
#include<stdio.h>Файл fortranCode1.f90:
void
c_function_(){
printf("Hello from C code!\n");
}
program helloКомпилируем и запускаем на выполнение:
implicit none
call c_function()
write (*,*)"Hello from FORTRAN code!"
end program hello
#gfortran -O2 -g -o fortranCode1.o -c fortranCode1.f90
#gcc -O2 -g -o cCode1.o -c cCode1.c
#gcc -L /usr/lib/gcc/i486-linux-gnu/4.7/ -lgfortran fortranCode1.o cCode1.o -o hello1
#./hello1
Нужно, чтобы присутствовала библиотека libgfortran.so
/usr/lib/gcc/i486-linux-gnu/4.7/ - это путь, по которомуона у меня лежит. У вас может быть другой путь.
Обратный случай:
Файл cCode2.c:
#include<stdio.h>Файл fortranCode2.f90:
void
main(){
fortran_function_();
printf("Hello from C code!\n");
}
subroutine fortran_functionКомпилируем и запускаем на выполнение:
implicit none
write (*,*)"Hello from FORTRAN code!"
end subroutine fortran_function
#gfortran -O2 -g -o fortranCode2.o -c fortranCode2.f90
#gcc -O2 -g -o cCode2.o -c cCode2.c
#gcc -L /usr/lib/gcc/i486-linux-gnu/4.7/ -lgfortran fortranCode2.o cCode2.o -o hello2
#./hello2
Теперь сделаем вызов функции с передачей параметров разных типов.
Файл cCode3.c:
#include<stdio.h>Файл fortranCode3.f90:
void
c_function_(signed char* a1, short* a2, int* a3, long int* a4){
printf("in called c function: \n%d\t%d\t%d\t%ld\n", *a1, *a2, *a3, *a4);
}
program hello#gfortran -O2 -g -o fortranCode3.o -c fortranCode3.f90
implicit none
integer*1 a1
integer*2 a2
integer*4 a3
integer*8 a4
a1=1
a2=22
a3=333
a4=4444
call c_function(a1, a2, a3, a4)
end program hello
#gcc -O2 -g -o cCode3.o -c cCode3.c
#gcc -L /usr/lib/gcc/i486-linux-gnu/4.7/ -lgfortran fortranCode3.o cCode3.o -o hello3
#./hello3
Файл cCode4.c:
#include<stdio.h>Файл fortranCode4.f90:
void
main(){
signed char a1 = 1;
short a2 = 22;
int a3 = 333;
long a4 = 4444;
fortran_function_(&a1, &a2, &a3, &a4);
}
subroutine fortran_function(f1, f2, f3, f4)#gfortran -O2 -g -o fortranCode4.o -c fortranCode4.f90
implicit none
integer*1 f1
integer*2 f2
integer*4 f3
integer*4 f4
write (*,100)f1,f2,f3,f4
100 format(4i5)
end subroutine fortran_function
#gcc -O2 -g -o cCode4.o -c cCode4.c
#gcc -L /usr/lib/gcc/i486-linux-gnu/4.7/ -lgfortran fortranCode4.o cCode4.o -o hello4
#./hello4
Теперь продемонстрируем передачу символьных строк из Си в Фортран и обратно.
Файл cCode5.c:
#include<stdio.h>Файл fortranCode5.f90:
void
c_function_(char* string){
printf("%s\n", string);
}
program hello#gfortran -O2 -g -o fortranCode5.o -c fortranCode5.f90
implicit none
character*37 string
string="Created in fortran, outputed from C!"
string(37:37)=char(0)
call c_function(string)
end program hello
#gcc -O2 -g -o cCode5.o -c cCode5.c
#gcc -L /usr/lib/gcc/i486-linux-gnu/4.7/ -lgfortran fortranCode5.o cCode5.o -o hello5
#./hello5
Теперь наоборот. Сформируем строку в Си, а напечатаем в Фортране.
Файл cCode6.c:
#include<string.h>Файл fortranCode6.f90:
void
main(){
char string[37];
int length = sizeof(string);
strncpy(string, "Created in C, outputed from Fortran!", length);
fortran_function_(string, &length);
}
subroutine fortran_function(string, length)#gfortran -O2 -g -o fortranCode6.o -c fortranCode6.f90
implicit none
character*(*) string
integer length
write(*,100)string(1:length)
100 format(a)
return
end subroutine fortran_function
#gcc -O2 -g -o cCode6.o -c cCode6.c
#gcc -L /usr/lib/gcc/i486-linux-gnu/4.7/ -lgfortran fortranCode6.o cCode6.o -o hello6
#./hello6
Все примеры протестированы в Debian Wheezy.