我正在从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例程,该例程指示何时可以释放该指针。

10-04 14:41