Why is this attempt to pass a pointer from C++ to Fortran not working?

别来无恙 提交于 2020-01-14 14:44:22

问题


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?


回答1:


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);



回答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.



来源:https://stackoverflow.com/questions/20249808/why-is-this-attempt-to-pass-a-pointer-from-c-to-fortran-not-working

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