我正在从C++调用Fortran函数,该函数分配了一个 vector ,然后它从C++返回一个指向该 vector 的指针。问题是,当我使用此指针在C++中打印值时, vector 的第一个元素的值会丢失。我不确定自己做错了什么。
以下是我的C++代码:
#include <iostream>
#include <cstdio>
using namespace std;
extern"C" {
void fortfunc_(int *ii, void *ff);
}
main()
{
int ii=5;
double *ff;
int i;
// Calling my Fortran function:
fortfunc_(&ii, &ff);
printf("#C++ address: %p\n", ff);
for (i=0; i<ii; i++)
printf(" ff[%3d] = %f\n",i,ff[i]);
return 0;
}
我的Fortran代码:
subroutine fortfunc(ii,ffp)
use, intrinsic :: iso_c_binding
integer(kind=4), intent(in) :: ii
type(C_PTR), intent(out) :: ffp
real(kind=8), dimension(:), allocatable, target :: ff
integer(kind=4) :: err, i
!Allocating memory for ff:
allocate(ff(ii),stat=err)
print *,'allocate returned: ',err
ffp = C_LOC(ff(1))
write(*,'(a,z20)') '#Fortran address:', C_LOC(ff(1))
do i=1,ii
ff(i) = i
end do
print*,"Writing some vectors:"
print*,"ii = ",ii
print*,"ff= ",ff
return
end
如果运行它,将获得以下输出:
allocate returned: 0
#Fortran address: 3B5AE0
Writing some vectors:
ii = 5
ff= 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000
#C++ address: 003B5AE0
ff[ 0] = 0.000000
ff[ 1] = 2.000000
ff[ 2] = 3.000000
ff[ 3] = 4.000000
ff[ 4] = 5.000000
如您所见,ff [0] = 0,并且必须为1。
最佳答案
如果引用的是ISO_C_BINDING内部模块,则您的Fortran编译器几乎可以肯定支持C互操作的Fortran过程和接口(interface)的BIND(C)后缀。将后缀BIND(C, NAME='what_you_want_the_thing_called_in_C")
放在子例程语句上,并避免Fortran过程的符号名周围所有依赖于处理器的愚蠢行为。这也确保以C互操作方式传递参数。
Fortran子例程中的ff
变量是未保存的本地可分配变量。从Fortran 95开始,子例程完成执行后,将自动解除分配。然后,该对象的第一个元素的C地址在那时将变为无效-因此,在C代码中,您尝试取消引用无效的指针(它指向不再分配的内存)。
您需要考虑一些管理Fortran ff
变量生命周期的方法。一种方法是使它成为Fortran指针,并提供一个单独的Fortran例程,该例程指示何时可以释放该指针。