如何为“分配”编写包装器
我正在尝试为“分配”函数编写一个包装器,即接收数组和维度、分配内存并返回分配的数组的函数。最重要的是该函数必须适用于不同等级的数组。但我必须在函数接口中显式声明数组的等级,在这种情况下,只有当我将特定等级的数组作为参数传递时,代码才会编译。例如,此代码无法编译:
module memory_allocator
contains
subroutine memory(array, length)
implicit none
real(8), allocatable, intent(out), dimension(:) :: array
integer, intent(in) :: length
integer :: ierr
print *, "memory: before: ", allocated(array)
allocate(array(length), stat=ierr)
if (ierr /= 0) then
print *, "error allocating memory: ierr=", ierr
end if
print *, "memory: after: ", allocated(array)
end subroutine memory
subroutine freem(array)
implicit none
real(8), allocatable, dimension(:) :: array
print *, "freem: before: ", allocated(array)
deallocate(array)
print *, "freem: after: ", allocated(array)
end subroutine freem
end module memory_allocator
program alloc
use memory_allocator
implicit none
integer, parameter :: n = 3
real(8), allocatable, dimension(:,:,:) :: foo
integer :: i, j, k
print *, "main: before memory: ", allocated(foo)
call memory(foo, n*n*n)
print *, "main: after memory: ", allocated(foo)
do i = 1,n
do j = 1,n
do k = 1, n
foo(i, j, k) = real(i*j*k)
end do
end do
end do
print *, foo
print *, "main: before freem: ", allocated(foo)
call freem(foo)
print *, "main: after freem: ", allocated(foo)
end program alloc
编译错误:
gfortran -o alloc alloc.f90 -std=f2003
alloc.f90:46.14:
call memory(foo, n*n*n)
1
Error: Rank mismatch in argument 'array' at (1) (1 and 3)
alloc.f90:60.13:
call freem(foo)
1
Error: Rank mismatch in argument 'array' at (1) (1 and 3)
有没有办法实现这样的包装器?..
谢谢!
I am trying to write a wrapper for 'allocate' function, i.e. function which receives an array and dimensions, allocates memory and returns allocated array. The most important thing is that the function must work with arrays of different rank. But I have to explicitly state rank of array in function interface, and in this case code only compiles if I pass arrays of certain rank as a parameter. For example, this code does not compile:
module memory_allocator
contains
subroutine memory(array, length)
implicit none
real(8), allocatable, intent(out), dimension(:) :: array
integer, intent(in) :: length
integer :: ierr
print *, "memory: before: ", allocated(array)
allocate(array(length), stat=ierr)
if (ierr /= 0) then
print *, "error allocating memory: ierr=", ierr
end if
print *, "memory: after: ", allocated(array)
end subroutine memory
subroutine freem(array)
implicit none
real(8), allocatable, dimension(:) :: array
print *, "freem: before: ", allocated(array)
deallocate(array)
print *, "freem: after: ", allocated(array)
end subroutine freem
end module memory_allocator
program alloc
use memory_allocator
implicit none
integer, parameter :: n = 3
real(8), allocatable, dimension(:,:,:) :: foo
integer :: i, j, k
print *, "main: before memory: ", allocated(foo)
call memory(foo, n*n*n)
print *, "main: after memory: ", allocated(foo)
do i = 1,n
do j = 1,n
do k = 1, n
foo(i, j, k) = real(i*j*k)
end do
end do
end do
print *, foo
print *, "main: before freem: ", allocated(foo)
call freem(foo)
print *, "main: after freem: ", allocated(foo)
end program alloc
Compilation error:
gfortran -o alloc alloc.f90 -std=f2003
alloc.f90:46.14:
call memory(foo, n*n*n)
1
Error: Rank mismatch in argument 'array' at (1) (1 and 3)
alloc.f90:60.13:
call freem(foo)
1
Error: Rank mismatch in argument 'array' at (1) (1 and 3)
Is there any way of implementing such wrapper?..
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这可以通过通用接口块来完成。您必须为要处理的每个等级创建过程,例如,内存_1d、内存_2d、...内存_4d。 (显然需要大量剪切和粘贴。)然后编写一个通用接口块,为所有这些过程提供替代名称内存作为通用过程名称。当您调用内存时,编译器会根据参数的级别来区分应该调用哪个内存_Xd。你的 freem 函数也是如此。
这就是诸如 sin 之类的内部函数长期以来的工作方式——您可以使用各种规定的实参数或复杂参数来调用 sin,编译器会计算出要调用的实际 sin 函数。在非常古老的 FORTRAN 中,您必须对不同的 sin 函数使用不同的名称。现在,使用现代 Fortran,您可以使用自己的例程设置相同的内容。
编辑:添加演示方法的代码示例 &句法:
This can be done via a generic interface block. You have to create procedures for each rank that you want to handle, e.g., memory_1d, memory_2d, ... memory_4d. (Obviously a lot of cut & pasting.) Then you write a generic interface block that gives all of these procedures the alternative name memory as a generic procedure name. When you call memory, the compiler distinguishes which memory_Xd should be called based on the rank of the argument. The same for your freem functions.
This is how intrinsic functions such as sin have long worked -- you can call sin with a real arguments of various previsions, or with a complex argument, and the compiler figures out with actual sin function to call. In really old FORTRAN you had to use different names for the different sin functions. Now modern Fortran you can setup the same thing with your own routines.
Edit: adding a code example demonstrating the method & syntax:
子例程内存(数组,长度)
具有第一个虚拟参数一维数组(real(8),allocatable,intent(out),dimension(: ) :: 数组
)。从主程序中使用 3 维数组 foo (
real(8), allocatable,Dimension(:,:,:) :: foo
) 调用这个子例程显然是错误的。这就是编译器实际上所说的。如果您确实需要这样的子例程,请为每个不同维度的数组编写一对
memory
/freem
子例程 - 一对子例程用于一维数组,另一对用于二维数组, 顺便说一句,内存子例程通常会有所不同,因为为了分配 n 维数组,您需要将 n 个范围传递给上述子例程。
subroutine memory(array, length)
has as it first dummy parameter 1-dimensional array (real(8), allocatable, intent(out), dimension(:) :: array
).Calling this subroutine from your main program with 3-dimensional array foo (
real(8), allocatable, dimension(:,:,:) :: foo
) is error obviously. And this is what compiler actually said.If you really need such subroutines write one pair
memory
/freem
subroutines for each array of different dimension - one subroutines pair for 1-dimensional array, another for 2-dimensional array, etc.By the way,
memory
subroutines will be different in general because in order to allocate n-dimensional array you need to pass n extents to above-mentioned subroutine.