2017-05-30 26 views
0

我們有運行在一組數據陣列的並想程度的代碼,以便我們可以有幾套的數據的傳統的Fortran 90的代碼。不幸的是,子程序都沒有輸入參數,而是通過模塊評估所有數據。以下代碼類似於我們的Fortran代碼。使用C指針跟蹤的Fortran模塊數據成員

MODULE test_mod 
    IMPLICIT NONE 

    double precision, pointer :: f_x(:) 
    integer :: n = 5 
END MODULE test_mod 

SUBROUTINE alloc_x() 
    use test_mod 
    IMPLICIT NONE 

    allocate(f_x(n)) 
END SUBROUTINE alloc_x 

SUBROUTINE init_x() 
    USE test_mod 
    IMPLICIT NONE 

    f_x = 1.0 
END SUBROUTINE init_x 

SUBROUTINE dealloc_x() 
    use test_mod 
    IMPLICIT NONE 

    deallocate(f_x) 
END SUBROUTINE dealloc_x 

由於Fortran代碼就夠了複雜(有大約一百陣列且全部在不同形狀和尺寸),則較少的代碼更好的修改。我們提出了以下解決方案,並對此解決方案是否與Fortran 90標準兼容感興趣:

我們創建了兩個額外的Fortran子例程,用於存儲分配的Fortran陣列的位置並將c指針複製回模塊。

#include <stdio.h> 
#include <stdlib.h> 

void alloc_x_(); 
void init_x_(); 
void dealloc_x_(); 
void store_ptrs_(double **c_x); 
void copy_ptrs2mod_(double **c_x); 

void output_result(int entry, double* array); 

int main() 
{ 
    int i; 
    double *x[10]; 

    /* allocate array */ 
    for(i=0; i<10; i++){ 
     alloc_x_(); 
     store_ptrs_(&x[i]); 
    } 

    /* initialize array */ 
    for(i=0; i<10; i++){ 
     copy_ptrs2mod_(&x[i]); 
     init_x_(); 
     output_result(i,x[i]); 
    } 

    /* deallocate the array */ 
    for(i=0; i<10; i++){ 
     copy_ptrs2mod_(&x[i]); 
     dealloc_x_(); 
    } 
} 

void output_result(int entry, double* array){ 
    int j; 
    printf("x[%2d] = [", entry); 
    for (j = 0; j < 5; ++j) 
    { 
     if (j == 4) 
     { 
      printf("%3.1f",array[j]); 
      continue; 
     } 
     printf("%3.1f, ",array[j]); 
    } 
    printf("]\n"); 
} 

輸出 - -

SUBROUTINE store_ptrs(c_x) 
    use iso_c_binding 
    use test_mod 
    IMPLICIT NONE 

    TYPE(c_ptr) :: c_x 

    c_x = c_loc(f_x) 
END SUBROUTINE 

SUBROUTINE copy_ptrs2mod(c_x) 
    use iso_c_binding 
    use test_mod 
    IMPLICIT NONE 

    TYPE(c_ptr) :: c_x 
    CALL c_f_pointer(c_x,f_x,[n]) 
END SUBROUTINE 

有了這兩個子程序,我們可以無需修改Fortran代碼有更多的數據是一個副本(在下面的代碼10份)

x[ 0] = [1.0, 1.0, 1.0, 1.0, 1.0] 
x[ 1] = [1.0, 1.0, 1.0, 1.0, 1.0] 
x[ 2] = [1.0, 1.0, 1.0, 1.0, 1.0] 
x[ 3] = [1.0, 1.0, 1.0, 1.0, 1.0] 
x[ 4] = [1.0, 1.0, 1.0, 1.0, 1.0] 
x[ 5] = [1.0, 1.0, 1.0, 1.0, 1.0] 
x[ 6] = [1.0, 1.0, 1.0, 1.0, 1.0] 
x[ 7] = [1.0, 1.0, 1.0, 1.0, 1.0] 
x[ 8] = [1.0, 1.0, 1.0, 1.0, 1.0] 
x[ 9] = [1.0, 1.0, 1.0, 1.0, 1.0] 

雖然我們還沒有看到任何這方面的問題,我們都有點擔心,我們可能會(隱含的)依靠編譯器的各種標準的具體實施中,或者一些其他incompa使用更新的標準可能會妨礙這項工作。我們將非常感謝您對此方法的任何意見或反饋,以處理舊版Fortran 90代碼中常見的問題。

+1

iso_c_binding'不規範直到2003年的Fortran – francescalus

+2

的Fortran 90是完全過時模塊'。忘記它,不需要符合Fortran 90。使用*至少* Fortran 95固定最大的問題,但更好的Fortran 2003或2008。 –

回答

0

我不會說你的代碼/方法是正確的,但我會識別出一件引起我最初關注的事情。你可以簡單解決這個問題。

從這個事實,你有名字改編給予,在C面,原型

void alloc_x_(); 
void init_x_(); 
void dealloc_x_(); 
void store_ptrs_(double **c_x); 
void copy_ptrs2mod_(double **c_x); 

這表明Fortran語言程序的任何模塊之外(你沒有bind(c,name='alloc_x_')等在子程序語句)。在Fortran 2008之前,有一個關於在活動範圍內不再引用模塊時模塊變量未定義的規則。

在你擁有它的C執行,alloc_x進入test_mod參考。但只要子程序完成,test_mod不再在任何活動範圍內被引用。在Fortran 90到Fortran 2003規則下,模塊變量f_x在該點處變得未定義。之後,在store_ptrs中,c_loc(f_x)中的參考不符合規定。

添加save屬性模塊局部變量,或之後的Fortran 2008標準,解決了這個問題。


說了這麼多,下面的Fortran 2003 C互操作性的規則,f_x不是c_loc有效的參數:一個指針參數必須是標量。

+1

你知道今天仍然使用的所有編譯器,其實際上表現如此。在一些舊版本中? –