pointers - Upgrading Fortran/C program from 32-bit to multi-architecture -


i'm looking @ old fortran program c calls works 32-bit systems, raises warnings , concerns 64-bit compilers. program stores address of c pointer dynamically allocated memory int, shared on fortran-side integer. concern on 64-bit integer systems, cast c pointer larger can stored int/integer. i've simplified existing program example 2 files.

fortran: this.f

        program         integer,pointer :: iptr         allocate(iptr)         call that_allocate(iptr)         write(*,'(a, z12)') 'fortran: iptr address', iptr         call that_assemble(iptr)         call that_free(iptr)         end program 

c: that.c

#include <stdlib.h> #include <stdio.h>  typedef struct data {     int a;     float b; } data;  void that_allocate_(int* iptr) {     data *pdata = calloc(1, sizeof(data));     *iptr = (int)pdata;     printf("c: allocated address %p (or %d)\n", pdata, pdata);     return; }  void that_assemble_(int* iptr) {     data *pdata = (data *) *iptr;     pdata->a = 42;     pdata->b = 3.1415926;     return; }  void that_free_(int* iptr) {     data *pdata = (data *) *iptr;     printf("c: freeing data %d , %g @ %p\n", pdata->a, pdata->b, pdata);     free(pdata);     return; } 

compile

the program can compiled gnu compilers -m32 32-bit (no issue here), , -m64 64-bit. compiling c code raises warnings:

$ gcc -m64 -c that.c that.c: in function ‘that_allocate_’: that.c:12: warning: cast pointer integer of different size that.c: in function ‘that_assemble_’: that.c:19: warning: cast pointer integer of different size that.c: in function ‘that_free_’: that.c:27: warning: cast pointer integer of different size 

while remaining compilation , linking fine, , program works:

$ gfortran -m64 -o prog this.f that.o $ ./prog  c: allocated address 0x1130b40 (or 18025280) fortran: iptr address     1130b40 c: freeing data 42 , 3.14159 @ 0x1130b40 

questions

while see calloc returned address can fit within data limits of 4-byte integer, there risk of calloc returning address larger integer? casting (intptr_t) silence the compile warnings, suspect truncate higher bits , "segmentation fault" if pointer attempted cast truncated address. correct?

what should do? fix need go on fortran code?

yes, there potential bitness problem. if want code robust in face of compiler , platform changes, there number of things should do, of rely on c interoperability features of fortran 2003. these language features supported recent gfortran , actively maintained fortran compilers.

it not clear example whether fortran code needs know value of pointer data struct integer (in example print value, suspect debugging). if fortran code needs regard pointer opaque handle, c_ptr type in iso_c_binding intrinsic module appropriate equivalent c pointer. if reason fortran code need know value of pointer integer, integer of kind c_intptr_t (again iso_c_binding intrinsic module) appropriate. going further still, if want fortran code able play actual structure itself, can define bind(c) derived type , use in various ways.

further, c code assumes fortran compiler uses calling convention, including way procedure names mangled form linker name. can use bind(c,name='xxx') attribute in interface block on fortran side specify fortran compiler use calling convention compatible companion c compiler , specify c name of procedure.

note pointer declaration on integer , subsequent allocation not relevant, given rest of example.

all (in free form, has been while since fixed form appropriate):

program   use, intrinsic :: iso_c_binding, only: c_ptr, c_intptr_t   implicit none   ! interfaces required due bind(c).  allows fortran    ! compiler better error checking.  note default    ! binding label lowercase variant of fortran name,   ! specify explicitly here anyway clarity.   interface     subroutine that_allocate(the_c_ptr)  &         bind(c,name='that_allocate')       use, intrinsic :: iso_c_binding, only: c_ptr       implicit none       ! note passing pointer reference.       type(c_ptr), intent(out) :: the_c_ptr     end subroutine that_allocate      subroutine that_assemble(the_c_ptr)  &         bind(c,name='that_assemble')       use, intrinsic :: iso_c_binding, only: c_ptr       implicit none       ! note passing pointer value.       type(c_ptr), intent(in), value :: the_c_ptr     end subroutine that_assemble      subroutine that_free(the_c_ptr)  &         bind(c,name='that_free')       use, intrinsic :: iso_c_binding, only: c_ptr       implicit none       ! note passing pointer value.       type(c_ptr), intent(in), value :: the_c_ptr     end subroutine that_free   end interface    type(c_ptr) :: the_c_ptr   call that_allocate(the_c_ptr)   ! use transfer convert c address integer value.   print "('fortran: ptr address',z12)",  &       transfer(the_c_ptr, 0_c_intptr_t)   call that_assemble(the_c_ptr)   call that_free(the_c_ptr) end program 

and simplifying on c side:

#include <stdlib.h> #include <stdio.h>  typedef struct data {   int a;   float b; } data;  void that_allocate(data** pdata) {     *pdata = (data*) calloc(1, sizeof(data));     printf("c: allocated address %p\n", *pdata);     return; }  void that_assemble(data* pdata) {     pdata->a = 42;     pdata->b = 3.1415926;     return; }  void that_free(data* pdata) {     printf("c: freeing data %d , %g @ %p\n", pdata->a, pdata->b, pdata);     free(pdata);     return; } 

Comments

Popular posts from this blog

sql - VB.NET Operand type clash: date is incompatible with int error -

SVG stroke-linecap doesn't work for circles in Firefox? -

python - TypeError: Scalar value for argument 'color' is not numeric in openCV -