Jam*_*mes 5 c fortran fortran-iso-c-binding
我将值分配给状态数组,如下所示:
status [i] + = 1;
我想从fortran访问这个数组
如何访问这个数组?
例如,我想从fortran更改STAT的值,如下所示:
STAT(2)= 3
这可能吗?
c来源
#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]);
}
}
Run Code Online (Sandbox Code Playgroud)
fortran来源
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
Run Code Online (Sandbox Code Playgroud)
我已经测试了这个代码,我提到了这个问题的好答案.但是当我尝试这样做时,我遇到了分段错误错误:
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
Run Code Online (Sandbox Code Playgroud)
你能意识到这件事是什么吗?
你必须以某种方式声明STAT.如果你开始使用动态内存分配,那么留在FORTRAN 77是没有希望的.也许有人能够提出一些解决方案,但这是我发现的最小变化.它使用Fortran 2003与C的互操作性.(也许Cray指针解决方案会更短,但非标准)
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
Run Code Online (Sandbox Code Playgroud)
我从你的C部分得到一些错误,我没有检查.我也不确切地知道该程序应该做什么.
但是我真的很鼓励你使用现代的Fortran功能.对于C和Fortran之间的互操作性,最重要的是ISO_C_BINDING.还忘记DATA语句并使用变量初始化.
快速翻译成更现代的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
Run Code Online (Sandbox Code Playgroud)