2013-07-17 73 views
3

我從FORTRAN 90代碼調用C例程。所有的工作都很好,但我想知道爲什麼和如何用更少的參數調用C程序,我應該讓編譯器不抱怨。編譯器在這裏做什麼?我正在使用Cray編譯器。不同數目的參數調用C例程從FORTRAN 90

test.c的

extern "C" void test_(double* x, double* y, double* z){ 
    // do some work 
} 

driver.F90

MODULE DRIVER 

! declare arrays 
DOUBLE PRECISION, DIMENSION(dim, dim), INTENT(IN) :: x 
DOUBLE PRECISION, DIMENSION(dim, dim), INTENT(IN) :: y 

! call C subroutine 
CALL test(x, y) 

END MODULE DRIVER 
+0

可能的測試函數會彈出一個未定義的值,表示Fortran沒有推入堆棧(或將null可能爲零)。例子:push x,y,z pop z,y,x但是沒有做最新的push,所以它是push x,y pop z(它是y),y(它是x),undefined x(沒有push/null) –

+2

在你的C打印z方法並找出答案。由於每個編譯器都不同,因此在調用外部方法時應始終確保傳入正確的編號參數。它要麼將z設置爲默認值(零或空值),要麼會損壞堆棧,並且您將遇到一些內存問題,可能會顯示更多內容...... – MoonKnight

+1

我不相信這是downvoted。 –

回答

8

Fortran語言是比C一個很大的不同,當涉及到函數調用。當傳遞參數給C例程,編譯器必須知道每個參數的類型,以便它可以生成相應的調用序列 - 要麼把參數堆棧上以正確的順序並用正確的填充或把他們的預期寄存器。如果在調用者之前定義了被調用者,那麼C編譯器通常在編譯代碼時收集這些信息。在所有其他情況下,應提供原型形式的函數聲明。

Fortran中所有參數通常是(有一些例外)的轉交地址,這意味着什麼是真正被傳遞給被叫方是一組內存指針。指針看起來是一樣的 - 它們總是相同的類型,因此以相同的方式傳遞。因此,Fortran編譯器可以在不知道被調用者實際期望的參數的情況下生成函數調用。這大大簡化了Fortran編譯器,但隨後可能出現的錯誤的無數的來源,比如調用函數與錯誤的參數類型或者即使有錯誤的參數數目,僅舉幾例。特別節目,叫做棉短絨(從C程序驗證工具lint的名稱),通常以被用來保證沒有這樣的錯誤都存在。現代Fortran編譯器也試圖比舊版編譯器嚴格得多,並儘可能地檢測錯誤。

現代Fortran版本提供了INTERFACE構造,允許顯式聲明函數接口,與C中的函數原型非常相似。模塊子例程和函數自動生成接口並使其可用於模塊的調用方。當調用具有顯式接口子程序/函數,編譯器能夠驗證電話的有效性,即它檢查的參數和它們的類型的數量相匹配的接口中。

您應該爲外部例程提供一個接口,然後編譯器將能夠執行檢查。人們通常使用ISO_C_BINDING方法以接口爲C代碼:

INTERFACE 
    SUBROUTINE test(x, y, z) BIND(C, NAME="test") 
    USE, INTRINSIC :: ISO_C_BINDING 
    REAL(KIND=C_DOUBLE), INTENT(...) :: x ! Put the proper intents 
    REAL(KIND=C_DOUBLE), INTENT(...) :: y 
    REAL(KIND=C_DOUBLE), INTENT(...) :: z 
    END SUBROUTINE test 
END INTERFACE 

有了這個接口,CALL test(x, y)會導致編譯時錯誤,因爲參數數量不匹配的。

+0

@_Hristo謝謝你。我會嘗試的。學習新東西總是健康的。 – Manolete