5

私はこのようにステータス配列に値を割り当てました:

status [i] + = 1;

そして、Fortranからこのアレイにアクセスするの
が好きです。どうすればこのアレイにアクセスできますか?
たとえば、次のようにSTATの値をFortranから変更したいと思います。

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]);
    }
}

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

私はこのコードをテストし、この質問に対する良い答えを参照しました。しかし、このようにしようとすると、セグメンテーション違反エラーが発生しました:

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

問題が何であるかを認識できますか?

4

1 に答える 1

7

なんとかしてSTATを宣言する必要があります。動的メモリ割り当てを使い始めた場合、FORTRAN77にとどまるのは絶望的です。誰かが何らかの解決策を思い付くことができるかもしれませんが、これは私が可能な限り最小の変更です。これは、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

チェックしなかった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
于 2012-12-06T08:48:02.573 に答える