Undestanding c_ptr in fortran

Viewed 60

I am having some problems understanding c_ptrs in Fortran. I wrote the following program to play with c pointers. The program is very simple, to understand just go the the main program. For example, the line

  call print_cptr_address(my_f_to_c_str("c_loc(ii)")  , c_loc(ii))

prints the address of c_loc(ii). The line

  call print_cptr_address(my_f_to_c_str("dh=c_loc(ii)")      , dh)

prints the address of stored by dh , where dh=c_loc(ii), and so on.

Here is the output on my computer

c_loc(ii)         : c pointer address 0x7ffe2f751228
cptr%dh=c_loc(ii) : c pointer address 0x55ea3c5050d0
cptr%dhp=>cptr%dh : c pointer address 0x55ea3c5050d0
dhp=>cptr%dhp     : c pointer address 0x55ea3c5050d0
dh_copy=cptr%dh   : c pointer address 0x7ffe2f751240
dh=c_loc(ii)      : c pointer address 0x7ffe2f751248

I would expect the addresses would be the same but they are not. Specially the first and last output. Can someone explain me why is this?

To reproduce, copy the code and run the makefile. I compiled it with gcc 10.2.1 20210110

CODE:


makefile

all:
  gcc -c test_cpart.c
  gfortran -c test_fpart.F90
  gfortran -o test test_cpart.o test_fpart.o

clean:
  rm test_c_ptr_m.mod test_fpart.o test_cpart.o

test_cpart.c

#include <stdio.h>
#include <stdlib.h>

void print_pointer_address(char* cstr, void *ptr) {
  printf("%s: c pointer address %p\n", cstr, ptr);
}

test_fpart.F90

module test_c_ptr_m
  use iso_c_binding
  implicit none

  type :: cptr_t
    type(c_ptr) :: dh = c_null_ptr
    type(c_ptr), pointer :: dhp => null()
  endtype

  interface
    subroutine print_cptr_address(cstr,ptr) bind(C, name="print_pointer_address")
        use, intrinsic :: iso_c_binding
        character(kind=c_char) :: cstr(*)
        type(c_ptr) :: ptr
    end subroutine
  end interface

contains

  function my_f_to_c_str(fstring) result(cstring)
    character(len=*) :: fstring
    character(len=:, kind=c_char), allocatable :: cstring
    cstring = C_CHAR_""//fstring//C_NULL_CHAR
  end function
end module test_c_ptr_m

program main
  use test_c_ptr_m
  use iso_c_binding

  integer(c_int), target :: ii
  type(cptr_t), target :: cptr
  type(c_ptr), pointer :: dhp => null()
  type(c_ptr) :: dh,dh_copy

  ii = 500
  cptr%dh = c_loc(ii)
  cptr%dhp => cptr%dh
  dhp      => cptr%dhp
  dh_copy  = cptr%dh
  dh = c_loc(ii)

  call print_cptr_address(my_f_to_c_str("c_loc(ii)")  , c_loc(ii))
  call print_cptr_address(my_f_to_c_str("cptr%dh=c_loc(ii)")  , cptr%dh)
  call print_cptr_address(my_f_to_c_str("cptr%dhp=>cptr%dh") , cptr%dhp)
  call print_cptr_address(my_f_to_c_str("dhp=>cptr%dhp")      , dhp)
  call print_cptr_address(my_f_to_c_str("dh_copy=cptr%dh")  , dh_copy)
  call print_cptr_address(my_f_to_c_str("dh=c_loc(ii)")      , dh)
end program main
0 Answers
Related