I allocated value to status array like this :
status[i] += 1;
and I like to access to this array from fortran
how can I access to this array?
for example I want to change the value of STAT from fortran like this :
STAT(2)=3
is this possible?
c source
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/stat.h>
void call_fc_ (int *key, int *addr, int *size, int *status)
{
int i;
int shmid;
void* shared_addr;
//printf("first ptr = %p\n", *addr);
shmid = shmget (*key, *size, IPC_CREAT | IPC_EXCL | 0666);
if (shmid == -1)
{
printf("shmget is failed!\n");
exit(0);
}
shared_addr = (void*) shmat(shmid, 0, 0);
status = (int*)shared_addr;
//printf("status ptr = %p\n", status);
int data_size = *size/sizeof(int);
for(i=0; i<data_size;i++) {
status[i] += 1;
printf("%d th value : %d \n", i, status[i]);
}
}
fortran source
IMPLICIT NONE
INTEGER*8 KEY,SIZE,ADDR
DATA KEY / 777 /
DATA SIZE / 64 /
!DATA ADDR / Z'b76fb000' /
CALL CALL_FC(KEY, ADDR, SIZE, STAT)
PRINT *, 'stat is : ', STAT
! CAN I ACCESS TO STAT LIKE THIS?
!DO I=1,10
!STAT(I) = STAT(I) + 5
!WRITE (*,*) STAT(I)
!END DO
I have been tested this code and I refered to good answers to this question. but I got an segmentation fault error when I tried to do like this :
integer(c_int) :: key = 777, ssize = 64, addr
integer, pointer, dimension(:) :: stat
type(c_ptr) :: statptr
!DATA KEY / 777 /
!DATA SIZE / 64 /
print *, 'before stat size = ', size(stat)
call call_fc(key, addr, ssize, statptr)
!print *, 'statptr = ', statptr
call c_f_pointer(statptr, stat, [ssize])
print *, 'after stat size = ', size(stat)
stat(1) = 111 <==
stat(2) = 222
stat(3) = 333
print *, 'stat : ', stat
can you recognize what the matter is?
Pointers are a new feature to the Fortran standard and bring Fortran 90 into line with languages like C. The use of pointers can provide: A flexible alternative to allocatable arrays. The tools to create and manipulate dynamic data structures (such as linked lists).
To access address of a variable to a pointer, we use the unary operator & (ampersand) that returns the address of that variable. For example &x gives us address of variable x.
The POINTER @ statement establishes pairs of variables and pointers.
Pointers save memory space. Execution time with pointers is faster because data are manipulated with the address, that is, direct access to memory location. Memory is accessed efficiently with the pointers. The pointer assigns and releases the memory as well.
You have to declare STAT somehow. If you start to play with dynamic memory allocation, staying in FORTRAN 77 is hopeless. Maybe someone id able to come up with some solution, but this is the smallest change I found possible. It uses Fortran 2003 interoperability with C.(Maybe Cray pointer solution would be shorter, but non-standard)
USE ISO_C_BINDING
IMPLICIT NONE
INTEGER(C_INT) KEY,SIZE,ADDR,I
DATA KEY / 777 /
DATA SIZE / 64 /
!DATA ADDR / Z'b76fb000' /
INTEGER,POINTER :: STAT(:)
TYPE(C_PTR) :: STATPTR
CALL CALL_FC(KEY, ADDR, SIZE, STATPTR)
call C_F_POINTER(STATPTR,STAT,(/SIZE/))
PRINT *, 'stat is : '
DO I=1,SIZE
PRINT *,STAT(I)
END DO
! CAN I ACCESS TO STAT LIKE THIS?
!DO I=1,10
!STAT(I) = STAT(I) + 5
!WRITE (*,*) STAT(I)
!END DO
END
I am getting some error from your C part, which I didn't check. Also I do not know exactly, what the program is supposed to do.
However I really encourage you to use modern Fortran features. Most important is ISO_C_BINDING for interoperability between C and Fortran. Also forget DATA
statements and use variable initialization.
Quick translation to a more modern Fortran:
use iso_c_binding
implicit none
interface
subroutine call_fc(key,addr,size,status) bind(C,name='call_fc_')
import
integer(c_int) :: key !intents should be added
integer(c_int) :: addr
integer(c_int) :: size
type(c_ptr) :: status
end subroutine
end interface
integer(c_int) :: key = 777, size=64,addr,i
integer(c_int),pointer :: stat(:)
type(C_ptr) :: statptr
call call_fc(key, addr, size, statptr)
call c_f_pointer(statptr,stat,(/size/))
print *, 'stat is : ',stat
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With