C语言中的回调函数用起来很简单,只要定义一个与要调用的函数具有相同参数和返回参数的函数指针就可以使用了,例如:
#include <stdio.h> void Woof() { printf("Woof\n"); } void Meouw() { printf("Meouw\n"); } typedef void (*SoundFunction)(); void MakeSoundTenTimes(SoundFunction soundFunc) { int i; for ( i = 0; i < 10; ++i ) soundFunc(); } int main() { MakeSoundTenTimes(Woof); MakeSoundTenTimes(Meouw); }
MakeSoundTenTimes
,在MakeSoundTenTimes
里就会分别调用Woof和Meouw函数来执行。
在Fortran90中要实现上面类似的功能要怎么做呢? 举例如下:
module Sounds contains subroutine Woof() print *,'Woof' end subroutine subroutine Meouw() print *,'Meouw' end subroutine subroutine MakeSoundTenTimes(soundFunc) integer :: i interface subroutine soundFunc() end subroutine end interface do i = 1, 10 call soundFunc() enddo end subroutine end module program main use Sounds call MakeSoundTenTimes(Woof) call MakeSoundTenTimes(Meouw) end program
上面的回调函数都没有传递参数,如果回调函数需要传递参数,而且被调用函数的参数不一样,那又该怎么办?
其实在C语言中很简单,只要在将被调用的函数的参数的类型设为void*,举例如下:
#include <stdio.h> void IncrementAndPrintFloat(void *data) { double *d = data; (*d)++; printf("%f\n", *d); } void IncrementAndPrintInteger(void *data) { int *i = data; (*i)++; printf("%d\n", *i); } typedef void (*IncrementFunction)(void*); void IncrementTenTimes(IncrementFunction incrFunc, void *data) { int i; for ( i = 0; i < 10; ++i ) incrFunc(data); } int main() { double f = 5.0; int i = 10; IncrementTenTimes(IncrementAndPrintFloat, &f); IncrementTenTimes(IncrementAndPrintInteger, &i); }
下面是采用transfer函数来实现类似以上功能的例程:
module Increments contains subroutine IncrementAndPrintReal(data) character(len=1) :: data(:) real :: r r = transfer(data, r) r = r + 1.0 print *,r data = transfer(r, data) end subroutine subroutine IncrementAndPrintInteger(data) character(len=1) :: data(:) integer :: i i = transfer(data, i) i = i + 1 print *,i data = transfer(i, data) end subroutine subroutine IncrementTenTimes(incrFunc, data) character(len=1) :: data(:) integer :: i interface subroutine incrFunc(data) character(len=1) :: data(:) end subroutine end interface do i = 1, 10 call incrFunc(data) enddo end subroutine end module program main use Increments character(len=1), allocatable :: data(:) integer :: lengthData real :: r = 5.0 integer :: i = 10 lengthData = size(transfer(r, data)) allocate(data(lengthData)) data = transfer(r, data) call IncrementTenTimes(IncrementAndPrintReal, data) deallocate(data) lengthData = size(transfer(i, data)) allocate(data(lengthData)) data = transfer(i, data) call IncrementTenTimes(IncrementAndPrintInteger, data) end program
transfer在数据类型的转换中是非常有用的,如果想了解更详细的内容请参考文章开头介绍的文章。