因此Fortran2003及其後續版本的一個優點是C互操作性爲定義爲成爲標準;這是一個PITA的使用,但一旦完成,它將保證跨平臺和編譯器工作。
所以這裏的cprogram.c
,來調用Fortran程序getstring
:
#include <stdio.h>
int main(int argc, char **argv) {
int l;
char *name="IGRF";
l = getstring(name);
printf("In C: l = %d\n",l);
return 0;
}
和這裏的fortranroutine.f90
:
integer(kind=c_int) function getstring(instr) bind(C,name='getstring')
use, intrinsic :: iso_c_binding
character(kind=c_char), dimension(*), intent(IN) :: instr
integer :: len
integer :: i
len=0
do
if (instr(len+1) == C_NULL_CHAR) exit
len = len + 1
end do
print *, 'In Fortran:'
print *, 'Got string: ', (instr(i),i=1,len)
getstring = len
end function getstring
生成文件很簡單:
CC=gcc
FC=gfortran
cprogram: cprogram.o fortranroutine.o
$(CC) -o cprogram cprogram.o fortranroutine.o -lgfortran
fortranroutine.o: fortranroutine.f90
$(FC) -c $^
clean:
rm -f *.o cprogram *~
並運行它的工作原理,在gcc/gfortran和icc/ifort下:
In Fortran:
Got string: IGRF
In C: l = 4
更新:哦,我只是意識到你正在做的,而不是僅僅傳遞字符串更復雜;你基本上試圖傳遞一個指向C回調例程的函數指針。這是一個小竅門,因爲你必須使用Fortran interface
來聲明C例程 - 只是使用extern將不起作用(因爲不存在類型檢查等問題,所以不如使用顯式接口)。應工作:
cprogram.c:
#include <stdio.h>
/* fortran routine prototype*/
int getstring(char *name, int (*)(int));
int square(int i) {
printf("In C called from Fortran:, ");
printf("%d squared is %d!\n",i,i*i);
return i*i;
}
int cube(int i) {
printf("In C called from Fortran:, ");
printf("%d cubed is %d!\n",i,i*i*i);
return i*i*i;
}
int main(int argc, char **argv) {
int l;
char *name="IGRF";
l = getstring(name, &square);
printf("In C: l = %d\n",l);
l = getstring(name, &cube);
printf("In C: l = %d\n",l);
return 0;
}
froutine。F90:
integer(kind=c_int) function getstring(str,func) bind(C,name='getstring')
use, intrinsic :: iso_c_binding
implicit none
character(kind=c_char), dimension(*), intent(in) :: str
type(c_funptr), value :: func
integer :: length
integer :: i
! prototype for the C function; take a c_int, return a c_int
interface
integer (kind=c_int) function croutine(inint) bind(C)
use, intrinsic :: iso_c_binding
implicit none
integer(kind=c_int), value :: inint
end function croutine
end interface
procedure(croutine), pointer :: cfun
integer(kind=c_int) :: clen
! convert C to fortran procedure pointer,
! that matches the prototype called "croutine"
call c_f_procpointer(func, cfun)
! find string length
length=0
do
if (str(length+1) == C_NULL_CHAR) exit
length = length + 1
end do
print *, 'In Fortran, got string: ', (str(i),i=1,length), '(',length,').'
print *, 'In Fortran, calling C function and passing length'
clen = length
getstring = cfun(clen)
end function getstring
和結果:
$ gcc -g -Wall -c -o cprogram.o cprogram.c
$ gfortran -c fortranroutine.f90 -g -Wall
$ gcc -o cprogram cprogram.o fortranroutine.o -lgfortran -g -Wall
$ gpc-f103n084-$ ./cprogram
./cprogram
In Fortran, got string: IGRF( 4).
In Fortran, calling C function and passing length
In C called from Fortran:, 4 squared is 16!
In C: l = 16
In Fortran, got string: IGRF( 4).
In Fortran, calling C function and passing length
In C called from Fortran:, 4 cubed is 64!
In C: l = 64
什麼你在做這個平臺嗎? – EvilTeach 2011-04-10 03:10:27
在Fedora 14(內核2.6.35.10-74)筆記本電腦上運行這個,用f95編譯(也嘗試過gfortran)和g ++ 4.5.1 – vityav 2011-04-10 04:35:45