the run time aborting when calling c++ sub from fortran

余生颓废 提交于 2020-01-11 04:16:07

问题


I had read many posts here about mixing languages use of Fortran and C++. However, I'm still stuck with my current problem: my Fortran program always aborted.


I have the Fortran program: test-cc.f90 and the C++ program: deb_cc.cc.

deb_cc.cc contains:

#include <iostream>
using namespace std;
extern "C" void deb_cc_(float*** rh,int* x, int* y , int* z_ext )
{
  cout <<"thinkdeb 1"<<endl;
  int i, j, k;
  cout <<"thinkdeb 1"<<endl;
  cout <<"thinktest i=8,j=4,k=1"<< " (*x) " << (*x)<<endl;
  cout <<"thinktest i=8,j=4,k=1"<< " x3/rh " << rh[1][1][1]<<endl; //abortion                        
                                                                //      here 
  cout <<"thinkdeb 7"<<endl;
  return;
}//end function

test-cc.f90 contains:

    use ISO_C_BINDING

    implicit none

    interface
      subroutine  deb_cc( rh,x,y,z_ext)
        use ISO_C_BINDING
        implicit none
        real(c_float),allocatable::rh(:,:,:)
        integer(c_int):: x,y,z_ext
      end subroutine
    end interface

    integer nx,ny,nz
    parameter (nx=10,ny=10,nz=10)
    real  ,dimension (:,:,:),allocatable:: x1
    integer:: iy1,iy2,iy3,iy4
    integer i,j,k

    allocate(x1(nx,ny,nz))

    do k=1,nz
      do j=1,ny
        do i=1,nx
          x1(i,j,k)=k*1000+j*100+i
        enddo
      enddo
    enddo

    iy1=nx
    iy2=ny
    iy3=nz

    call deb_cc(x1,iy1,iy2,iy3)

  end

I compiled them by pgf90 -c test-cc.f90 and pgcpp -c deb_cc.cc Finally, I linked them by pgf90 -pgcpplibs test-cc.o deb_cc.o. The output is:

 thinktest in test- x1 (8,2,2) is     2208.000
 thinkdeb 1
 thinkdeb 1
 thinktest i=8,j=4,k=1 (*x) 10
 Segmentation fault (core dumped)

回答1:


You use the iso_c_binding module, but your procedure interface is not C interoperable.

The iso_c_binding module is not the most important thing. The bind(C) attribute is the key. (I ranted several times about the unfortunate name of the tag here)

You use an assumed shape allocatable array argument

real(c_float),allocatable::rh(:,:,:)

these are not allowed in interoperable procedures in Fortran 2008, because C or C++ have no idea what to do with them. They are not just addresses. If you used the bind(C) attribute in the interface, the compiler should tell you it is wrong.

There is a possibility to pass them in the next Fortran standard (in an existing TS actually) using a special C header, but some compilers (notably gfortran) are still not compatible.

As you do not do any reallocation on the C side (at least in your example), you can just pass the array as an assumed size (array(*)) argument. I also changed the C++ name, no need for the underscore.

interface
  subroutine  deb_cc(rh,x,y,z_ext) bind(C, name="deb_cc")
    use ISO_C_BINDING
    real(c_float) :: rh(*)
    integer(c_int):: x,y,z_ext
   end subroutine
end interface

On the C side, you cannot use the C arrays which are pointers to pointers ([i][j][k]). What you receive from Fortran is a single block of memory. You also have to pass the array shape. At least in the first two Fortan dimensions.

I would just use a macro to index the array in C.

// adjust as needed, many variants possible
#define IND(i,j,k) = i + (j-1) * nx + (k-1) * nx * ny
// adjust as needed, many variants possible


extern "C" void deb_cc(float *rh, int *nx, int *ny, int *nz) {
  cout <<"thinktest i=8,j=4,k=1"<< " x3/rh " << rh(IND(8,4,1))<<endl; 
}


来源:https://stackoverflow.com/questions/29132606/the-run-time-aborting-when-calling-c-sub-from-fortran

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!