【发布时间】:2017-08-16 12:31:52
【问题描述】:
我有以下类型的子例程包装器将 Fortran 数组传递给ISO_C_BINDING-bound C 函数。
subroutine mysub( array )
integer, dimension(:) :: array
call f_mysub( size(array) , array(1) )
end subroutine
问题在于,如果数组的大小为 0,那么 array(1) 就会越界。处理这种情况的正确方法是什么?
一般来说,我无法避免通话,即使用if( size(array) > 0 ),因为通话可能对注册很重要,例如它实际上是一个类方法,与上面的签名自然不同,并且可以清除现有数组。
示例文件
C 例程是c_mysub.c。
#include <stdio.h>
void c_mysub( size_t* size, int* arr )
{
printf("size=%d\n",*size);
for(size_t i=0; i<*size; ++i)
{
printf("element %d=%d\n",i,arr[i]);
}
}
主Fortran文件是mysub.f90
module mysub_I
interface
subroutine f_mysub( size, arr) BIND(C,name="c_mysub")
use,intrinsic :: ISO_C_BINDING
integer(C_SIZE_T) :: size
integer(C_INT) :: arr
end subroutine
end interface
end module
module mysub_M
use mysub_I
contains
subroutine mysub( array )
use ISO_C_BINDING
integer, dimension(:) :: array
call f_mysub( int(size(array),C_SIZE_T) , array(1) )
end subroutine
end module
program main
use mysub_M
integer, allocatable :: x(:)
allocate( x(7) )
x=1
call mysub( x )
deallocate( x )
allocate( x(0) )
call mysub( x )
end
使用 gcc -c c_mysub.c 编译 C 和使用 gfortran -fbounds-check c_mysub.o mysub.f90 编译 Fortran,当您运行代码时会出现以下错误,在 size=0 的第二次调用中犹豫不决。
size=7
0:1
1:1
2:1
3:1
4:1
5:1
6:1
At line 18 of file mysub.f90
Fortran runtime error: Index '1' of dimension 1 of array 'array' above upper bound of 0
在关闭边界检查的情况下进行编译的行为符合预期。
size=7
0:1
1:1
2:1
3:1
4:1
5:1
6:1
size=0
【问题讨论】:
-
如果数组为空,您可以暂时将数组维度设为 1。
-
... 或者准备一个虚拟数组以备不时之需。
-
c_mysub的接口是什么?为什么你希望将一个标量数组元素传递给它,即使数组可能没有元素? -
只是为了备份 francescalus 你为什么不只是传递数组?
-
通常你应该只通过
array,而不是array(1)。如果您不显示真实代码,很难说更多。array存在不连续的风险,array(1)将避免创建临时副本,这实际上可能是错误的。
标签: c arrays fortran fortran-iso-c-binding