ziv
ziv

Reputation: 189

c_f_pointer does not work

I have a very simple program which made me very confused. The call to c_f_pointer does not work, apparently I am making lots of mistakes!

program test
use iso_c_binding
implicit none
interface
subroutine call_fc(size,status) bind(C,name='call_fc_')
  import
  integer(c_int) :: size
  type(c_ptr) :: status
end subroutine
end interface
integer(c_int) :: size=8,i
integer(c_int),pointer  :: stat(:)
type(C_ptr) :: statptr
call call_fc(size, statptr)
call c_f_pointer(statptr,stat,(/size/))
print *, 'stat is : ',stat
end program test   

and the c++ subroutine is

extern "C" {
void call_fc_(int *size, int *status)
{
    int i;
    for(i=0; i<*size;i++) {
        status[i] = i+10;
        printf("%d th value : %d \n", i, status[i]);
    }   
}
}

when I compile and run the code it will produce the following error

0 th value : 10 
1 th value : 11 
2 th value : 12 
3 th value : 13 
4 th value : 14 
5 th value : 15 
6 th value : 16 
7 th value : 17 

Program received signal SIGSEGV: Segmentation fault - invalid memory reference. 

Can anybody tell me what is going wrong?

Upvotes: 0

Views: 549

Answers (3)

ziv
ziv

Reputation: 189

Thanks a lot. My problem just solved, the purpose of this example was only to allocate a memory in C or C++ subroutine and pass the allocated memory to FORTRAN, other wise, I also know that it is not necessary to do this.

program test
use iso_c_binding
implicit none
interface
function call_fc(size) bind(C,name='call_fc')
  import :: c_int, c_ptr
  integer(c_int) :: size
  type(c_ptr) :: call_fc
end function
end interface
integer(c_int) :: size=8,i
integer(c_int),pointer  :: stat(:)
call c_f_pointer(call_fc(size),stat,(/size/))
print *, 'stat is : ',stat
end program test   

and the c++ subroutine is

extern "C" {
void * call_fc(int *size)
{
    int i;
    int * status = new int [*size];
    for(i=0; i<*size;i++) {
        status[i] = i+10;
        printf("%d th value : %d \n", i, status[i]);
    }   
    return status;
}
}

when I compile and run the code it will produce the correct answer

0 th value : 10 
1 th value : 11 
2 th value : 12 
3 th value : 13 
4 th value : 14 
5 th value : 15 
6 th value : 16 
7 th value : 17 

stat is : 10   11    12   13   14   15   16   17

Upvotes: 1

I would also add, that If you want for some reason pass type(c_ptr) (e.g., to be able to pass null), you have to use the value attribute, if the argument on the C side is just a pointer passed by value as in your example.

interface
  subroutine call_fc(size,status) bind(C,name='call_fc_')
    import
    integer(c_int) :: size
    type(c_ptr), value :: status
  end subroutine
end interface

even after that your particular C procedure requires the passed pointer to point to some valid piece of memory (of size size*sizeof(int)).

Upvotes: 0

francescalus
francescalus

Reputation: 32366

No memory has been allocated for stat/status.

If the goal is to have an integer array passed to the C++ subroutine then c_f_pointer isn't required:

program test
  use iso_c_binding

  implicit none

  interface
     subroutine call_fc(size,status) bind(C,name='call_fc_')
       import c_int
       integer(c_int) :: size
       integer(c_int) :: status(size)
     end subroutine call_fc
  end interface

  integer(c_int), parameter :: size=8
  integer(c_int) stat(size)

  call call_fc(size, stat)

  print *, 'stat is : ',stat
end program test

Upvotes: 1

Related Questions