Domanda

I need to pass a dynamic array from c++ to Fortran. I did a lot of research to put together an example that I thought should work, but it doesn't. The program should create an array in the c++ program, pass the pointer of that array to the Fortran routine, convert the C pointer to a Fortran pointer, and then print the array on the Fortran side.

My c++ main program:

using namespace std;

extern "C" {
   void cinterface(int*,int*);
}

int main()
{
   int carray[]={0,1,2,3,4};
   int carray_siz=5;

   cinterface(&carray_siz,carray);

   return 0;
}

My Fortran routine:

module fortmod

   use ISO_C_BINDING

   implicit none

contains

   subroutine cinterface(carray_siz,carray_ptr) bind(C)

      implicit none

      integer(c_int), intent(in) :: carray_siz
      type(c_ptr), intent(in) :: carray_ptr

      integer(c_int), pointer :: pfarray(:) => NULL()

      call C_F_POINTER(carray_ptr,pfarray,[carray_siz])

      print *, pfarray

   end subroutine cinterface

end module fortmod

I build this as:

gfortran -c fortmod.f90
g++ main.cpp fortmod.o -lgfortran

But when I run it, instead of printing the array values, it says:

Segmentation fault (core dumped)

I'm new to the idea of pointers, so I'm thinking I'm not understanding how they work correctly. Can you please point out why I'm getting this memory error when I run this?

È stato utile?

Soluzione 2

From the gfortran manual:

If a pointer is a dummy-argument of an interoperable procedure, it usually has to be declared using the VALUE attribute. void* matches TYPE(C_PTR), VALUE, while TYPE(C_PTR) alone matches void**.

My Fortran routine was looking for the address of the pointer, not the address to which the pointer is pointing. So if I modify the c++ side to this:

using namespace std;

extern "C" {
   void cinterface(int*,int**);
}

int main()
{
   int carray[]={0,1,2,3,4};
   int carray_siz=5;

   cinterface(&carray_siz,&carray);

   return 0;
}

re-build and re-run, I now get:

0     1     2     3     4

as expected.

Altri suggerimenti

Surely you want to pass the array size as int, not the address of the size:

extern "C" {
    void cinterface(int,int*);
}

cinterface(carray_siz,carray);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top