gpt4 book ai didi

无法从 Fortran 90 中返回的 C 浮点指针获取数据

转载 作者:行者123 更新时间:2023-12-02 22:09:23 25 4
gpt4 key购买 nike

我正在从 Fortran 90 程序调用 C 函数(我必须使用 Fortran 90)。这个 C 函数接受几个参数并返回一个浮点指针。我似乎无法在 Fortran 代码中正确打印返回的数据。它只是显示一个非常大的数字(我假设这是指针的地址。)

我已经成功地将真正的 Fortran 变量作为参数传递,让 C 函数设置它们(因为 Fortran 通过引用传递)然后访问数据。但是,我必须将指针作为返回变量返回,因为这是遗留函数使用的方法(我正在重新实现)。

在 Fortran 90 中有没有一种方法可以从 C 函数返回的非字符(real、int 等)指针访问数据? (请注意:我不能使用 ISO C 绑定(bind),因为它仅适用于 Fortran 2003 及更高版本。)我已经在下面提出了我正在尝试做的事情的想法......

谢谢!

Fortran 程序

program test_real
real, dimension(10) :: realpt
integer nbr
integer i
real :: a=1.0
real :: b=2.0
real :: c=3.0

nbr = 9
realpt = getpointer(a, b, c)

do 10 i = 1, nbr
print *,"return: ",realpt(i)
10 continue

stop
End

C函数

float* getpointer(float *a, float *b, float *c) {
float *rfl = (float *) calloc(9,sizeof(float));
int i=0;

for(i=0;i<3;i++) {
rfl[i] = *a;
}
for(i=3;i<6;i++) {
rfl[i] = *b;
}
for(i=6;i<9;i++) {
rfl[i] = *c;
}
return(rfl);
} // End of getpointer function

输出

return:   3.1661344E+07
return: 3.1661344E+07
return: 3.1661344E+07
return: 3.1661344E+07
return: 3.1661344E+07
return: 3.1661344E+07
return: 3.1661344E+07
return: 3.1661344E+07
return: 3.1661344E+07

最佳答案

此声明“我不能使用 ISO C 绑定(bind),因为它仅适用于 Fortran 2003 及更高版本。”是奇数;当前任何支持 F90 的编译器也支持大部分或全部 F2003。

正如 Eric Urban 指出的那样,最简单的方法当然是在 fortran 中进行数组分配(您实际上可以使用数组切片或广播来更轻松地进行填充)。但假设有一些 C 例程需要调用采用这种形式,只需使用 ISO_C_BINDING C 和 Fortran 之间的可移植接口(interface)模块:

program test_real
use, intrinsic :: iso_c_binding
real(kind=c_float), pointer :: realpt(:)
type(c_ptr) :: ptr
integer :: nbr
integer :: i
real :: a=1.0
real :: b=2.0
real :: c=3.0

interface
function getpointer(a, b, c) result(ptr) bind(C,name="getpointer")
use, intrinsic :: iso_c_binding
implicit none
type(c_ptr) :: ptr
real(kind=c_float) :: a, b, c
end function getpointer
end interface

nbr = 9
ptr = getpointer(a, b, c)
call c_f_pointer(ptr, realpt, [nbr])

print *,"return: ",realpt
end

编译运行给出

$ gcc -c fooc.c
$ gfortran -c foo.f90
$ gfortran -o foo foo.o fooc.o
$ ./foo
return: 1.0000000 1.0000000 1.0000000 2.0000000 2.0000000 2.0000000 3.0000000 3.0000000 3.0000000

如果您尝试以某种方式执行此操作以绕过 7 年以上编译器的限制,有许多脆弱的不可移植的方法可以做到这一点,但这真的不值得为此心痛。

更新:如果您不能接触(甚至重新编译)一些较旧的 fortran,那么您至少可以为 C 程序制作一个 F2003 包装器,并让较旧的 fortran 链接到它:

foowrapper.f90:

module wrapper

contains

subroutine wrapgetpointer(outarr)
use, intrinsic :: iso_c_binding
implicit none

real, intent(out), dimension(:) :: outarr
real(kind=c_float), pointer :: realpt(:)
type(c_ptr) :: ptr
integer :: nbr = 9
real(kind=c_float) :: a, b, c

interface
function getpointer(a, b, c) result(ptr) bind(C,name="getpointer")
use, intrinsic :: iso_c_binding
implicit none
type(c_ptr) :: ptr
real(kind=c_float) :: a, b, c
end function getpointer
end interface

a = 1.
b = 2.
c = 3.
ptr = getpointer(a, b, c)
call c_f_pointer(ptr, realpt, [nbr])

outarr(1:nbr) = realpt
end subroutine wrapgetpointer

end module wrapper

foo.f90:

program test_real
use wrapper

real, dimension(9) :: array
call wrapgetpointer(array)

print *,"return: ",array
end

编译运行:

$ gfortran -c foowrapper.f90
$ gfortran -c foo.f90
$ gcc -c fooc.c
$ gfortran -o foo foo.o foowrapper.o fooc.o
$ ./foo
return: 1.0000000 1.0000000 1.0000000 2.0000000 2.0000000 2.0000000 3.0000000 3.0000000 3.0000000

关于无法从 Fortran 90 中返回的 C 浮点指针获取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15578979/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com