C语言中的回调函数用起来很简单,只要定义一个与要调用的函数具有相同参数和返回参数的函数指针就可以使用了,例如:
#include
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
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在数据类型的转换中是非常有用的,如果想了解更详细的内容请参考文章开头介绍的文章。