2012-12-06 14 views
5

ステータス配列に値を割り当てました。FortranからどのようにCポインタにアクセスできますか?

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

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 

あなたは問題が何であるかを認識することができます が、私はこのように実行しようとしましたセグメンテーションフォールトエラーを得ましたか。

答えて

7

何らかの理由でSTATを宣言する必要があります。動的メモリ割り当てでプレイを開始すると、FORTRAN 77にとどまることは望めないことです。たぶん、誰かが何らかの解決策を考え出すことができるかもしれませんが、これは私が可能であると考えた最も小さな変化です。それは私が私がチェックしていなかった、あなたのCの部分、からいくつかのエラーを取得しています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 

を使用しています。また、私はプログラムが何をすべきかを正確には知らない。

しかし、現代の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 
+4

1:私は助け、人々はFORTRAN77、これらの日を書くことだと思うが、私はステージに持っては非倫理的です。私は彼らがそれを書き直すのを手伝ってくれるだろうが、FORTRAN77に新しいコードを書く良い理由はない。 –

+1

そこにあるルーチンのインターフェイスブロックもよくポップします。 OPは非標準のINTEGER * 8をINTEGER(C_INT)に置き換えなければなりません。さもなければ、多くの現在のシステムで整数サイズの不一致が発生する可能性があります。 – IanH

+0

あなたは間違いなく、互換性のない種類の整数を使用しています。 –

関連する問題