当我将一个指针从 Fortran 传递给 C++ 时,第一个元素的值丢失了

When I pass a pointer from Fortran to C++ the value of the first element is lost

我正在从 C++ 调用 Fortran 函数,它分配一个向量,然后它 returns 从 C++ 到该向量的指针。问题是,当我使用此指针在 C++ 中打印值时,向量第一个元素的值丢失了。我不确定我是否做错了。

以下是我的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 过程和接口的 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 例程来指示何时可以释放该指针。