2012-12-06 22 views
5

Tôi đã phân bổ giá trị cho mảng trạng thái như sau:làm thế nào tôi có thể truy cập một con trỏ C từ fortran?

trạng thái [i] + = 1;

và tôi muốn truy cập mảng này từ fortran
làm cách nào tôi có thể truy cập vào mảng này?
ví dụ tôi muốn thay đổi giá trị của STAT từ fortran như thế này:

STAT (2) = 3

có thể như vậy?

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

nguồn 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 

tôi đã được thử nghiệm mã này và tôi giới thiệu đến câu trả lời tốt cho câu hỏi này. nhưng tôi gặp lỗi khi phân đoạn khi cố gắng thực hiện như sau:

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 

bạn có thể nhận ra vấn đề là gì không?

Trả lời

7

Bạn phải khai báo STAT bằng cách nào đó. Nếu bạn bắt đầu chơi với phân bổ bộ nhớ động, ở lại FORTRAN 77 là vô vọng. Có lẽ ai đó id có thể đưa ra một số giải pháp, nhưng đây là sự thay đổi nhỏ nhất mà tôi thấy có thể. Nó sử dụng khả năng tương tác của Fortran 2003 với C. (Có thể giải pháp con trỏ Cray sẽ ngắn hơn, nhưng không chuẩn)

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 

Tôi nhận được một số lỗi từ phần C của bạn mà tôi không kiểm tra. Ngoài ra tôi không biết chính xác, những gì chương trình được cho là phải làm.

Tuy nhiên, tôi thực sự khuyến khích bạn sử dụng các tính năng Fortran hiện đại. Quan trọng nhất là ISO_C_BINDING cho khả năng tương tác giữa C và Fortran. Đồng thời, hãy quên các tuyên bố DATA và sử dụng khởi tạo biến.

nhanh dịch để một Fortran hiện đại hơn:

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: nhưng tôi đã có vào giai đoạn mà tôi nghĩ rằng giúp đỡ mọi người để viết FORTRAN77 những ngày này là phi đạo đức; Tôi sẽ giúp họ viết lại nó nhưng không có lý do chính đáng để viết mã mới trong FORTRAN77. –

+1

Tốt hơn hãy bật khối giao diện cho thường trình trong đó. OP cũng nên thay thế 'INTEGER * 8' không chuẩn với' INTEGER (C_INT) ', nếu không có khả năng là một kích thước nguyên không khớp trên nhiều hệ thống hiện tại. – IanH

+0

Bạn chắc chắn đúng với loại số nguyên, không tương thích. –