Reputation: 189
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
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
Reputation: 60018
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
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