的Fortran-C的互操作性和浮动阵列 [英] Fortran-C interoperability and float arrays
问题描述
我有一个大现有Fortran95 code。它采用
I have a large existing Fortran95 code. It uses
real(dp), dimension(num) :: array
要声明数组。
我想在一些C code加入,我发现我可以通过写接口的C函数,并宣布数组作为
I want to join in some C code and found that I can do this by writing interfaces to the C-functions and declaring arrays as
use iso_c_binding
real(c_double), allocatable, target :: array(:)
我有工作调用其中的C-功能
I have working fortran functions which call the C-functions as
call myfunction(c_loc(array));
什么是需要通过实(DP)
数组MyFunction的?很显然,我需要从中进行C-指针(如何?)。是否有任何其他方式比复制数组?是有可能确保这两种类型的确参考兼容双precision数据块?最重要的是解决方案,必须与GNU编译器。请注意,以实(c_double)替换
在现有的Fortran code无处不在对我来说现在的选项。实(DP)
What is needed to pass the real(dp)
array to myfunction? Apparently, I would need to make a C-pointer from it (how?). Is there any other way than copying the array? Is it possible to ensure that both types indeed refer to compatible double precision data blocks? Most importantly the solution must work with the GNU compilers. Note, that replacing real(dp)
with real(c_double)
everywhere in the existing Fortran code is not an option for me right now.
在情况下没有替代复制整个数组,我怎么会在界面上做正确的?
In case there is no alternative to copying the entire array, how would I do this properly in the interface?
推荐答案
首先,我假设你定义DP作为一个地方模块中的参数。你可以简单地用
First, I assume you define dp as a parameter in a module somewhere. You can simply use
integer, parameter :: dp = c_double
(和
在该模块中有如果(DP / = c_double)停止Bletchful系统正
的某个地方。
在C和Fortran语言的数组是这样的:
Passing an array between C and Fortran works like this:
module foo
use iso_c_binding
private
public :: bar
interface
subroutine bar(a,n) bind(C)
import
real(kind=c_double), dimension(*), intent(inout) :: a
integer(c_size_t), value, intent(in) :: n
end subroutine bar
end interface
end module foo
然后,您的C函数是
Your C function then would be
void bar(double *a, size_t n)
编辑:
然后调用从你的Fortran C函数的方法是将
The way to call your C function from Fortran would then be
program main
use iso_c_binding
use foo
real(c_double), dimension(10) :: a
call bar(a,size(a,kind=c_size_t))
print *,a
end program main
编辑2:
如果你真的想这样做拷入/每次复制出来,你可以这样做
If you really want to do copy-in / copy-out each time, you can do something like
subroutine bar2(array)
real(kind=c_double), intent(inout), dimension(:) :: array
real(kind=c_double), dimension(size(array)) :: a
a = array ! Copy in
call bar(a,size(a,kind=c_size_t))
array = a ! Copy out
end subroutine bar2
end module foo
但我茫然地理解为什么这是必要的。
But I am at a loss to understand why this would be necessary.
修改3:
如果你是怕C和Fortran数据类型之间不匹配的,你可以写一个通用的包装来解决这个问题。这是它可能看起来是这样的:
If you are afraid of a mismatch between C and Fortran datatypes, you can write a generic wrapper to get around this. This is what it could look like:
module foo
use iso_c_binding
implicit none
private
public :: bar
interface
subroutine bar_double(a,n) bind(C)
import
real(kind=c_double), dimension(*), intent(inout) :: a
integer(c_size_t), value, intent(in) :: n
end subroutine bar_double
end interface
interface
subroutine bar_float(a,n) bind(C)
import
real(kind=c_float), dimension(*), intent(inout) :: a
integer(c_size_t), value, intent(in) :: n
end subroutine bar_float
end interface
interface bar
module procedure bar_aux_double, bar_aux_float
end interface bar
contains
subroutine bar_aux_double (a)
real(kind=c_double), dimension(:), intent(inout) :: a
call bar_double (a, size(a,kind=c_size_t))
end subroutine bar_aux_double
subroutine bar_aux_float (a)
real(kind=c_float), dimension(:), intent(inout) :: a
call bar_float (a, size(a,kind=c_size_t))
end subroutine bar_aux_float
end module foo
然后你的主程序可能看起来像
Your main program then could look like
program main
use foo
integer, parameter :: dp = selected_real_kind(15)
integer, parameter :: sp = selected_real_kind(6)
real(dp), dimension(10) :: a_dp
real(sp), dimension(10) :: a_sp
call bar(a_dp)
call bar(a_sp)
print *,a_dp,a_sp
end program main
在这里你不要做任何提及ISO_C_BINDING的。如果对DP或SP没有包装函数,编译将失败由于缺乏一个通用的程序。
where you don't make any reference to iso_c_binding at all. If there is no wrapper function for dp or sp, compilation will fail for lack of a generic procedure.
这篇关于的Fortran-C的互操作性和浮动阵列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!