2011-09-28 37 views
2

我想製作一個有用的函數庫。我對這個知之甚少,但顯然它們中的大多數(如果不是全部的話)都需要包含在模塊中(或者在程序中的一個接口中),但是因爲這是爲了創建一個庫,這似乎不是一種選擇),否則我將使用它們的程序將無法識別它們。有組織的函數庫與Fortran函數

我可以製作一個包含所有這些功能的模塊的長文件,但我希望將不同的功能保留在不同的短文件中。但是,如果我這樣做,我將不得不爲每個函數創建一個不同的模塊,並且如果我想在程序中使用它們,我會有一個很長的USE聲明列表(更不用說.mod文件的數量了那將會產生)。

對於這個我唯一可能的解決方案就是爲所有其他模塊創建另一個模塊,其中只有USE聲明,但是我認爲必須有另一種方法來創建一個包含不是目前爲止的函數的庫牽強。


此外,爲什麼我有這個問題的功能,但沒有子程序?是因爲命令CALL立即將該行標識爲子例程調用,而函數只是通過名稱調用,而沒有命令告訴編譯器「嘿,這是一個函數」,所以它必須知道什麼是函數,什麼不是事先指定的?


我包括一個示例(按照http://www.oceanographers.net/forums/showthread.php?378-How-to-make-a-FORTRAN-library中的說明,並使用正確的'路徑')。

TestFunc.F90

FUNCTION SumNum(nNum1,nNum2) RESULT(nResult) 
IMPLICIT NONE 
INTEGER,INTENT(IN) :: nNum1,nNum2 
INTEGER   :: nResult 

nResult=nNum1+nNum2 

RETURN;END FUNCTION 

TestProg.F90

PROGRAM TestProg 
IMPLICIT NONE 

WRITE(6,*) SumNum(2,2) 

STOP;END PROGRAM 

命令行

> gfortran -c TestFunc.F90 -o TestFunc.o 
> ar ruv libmylib.a *.o 
> gfortran TestProg.F90 -o Test.x -L/path -lmylib.a 

TestProg.F90:6.12: 

    WRITE(6,*) SumNum(2,2) 
       1 
Error: Function 'sumnum' at (1) has no IMPLICIT type 

回答

4

你並不需要把子程序模塊,以使庫。我最常做的是在不同的文件中的子程序,建立目標文件(.o)了他們,然後將它們歸檔到庫中,如:

ar ruv mylib.a *.o 

然後,所有它需要的是在指定m​​ylib.a上與調用子程序的主程序鏈接。無論你的程序是一個子程序還是一個函數,都沒有什麼不同。

EDIT1: 主程序需要有一個函數聲明:

PROGRAM TestProg 
IMPLICIT NONE 
INTEGER :: sumnum 

WRITE(6,*) SumNum(2,2) 

STOP;END PROGRAM 

然後:

gfortran -c *.f90 
ar ruv mylib.a testfunc.o 
gfortran testprog.o -o x mylib.a 

當我運行X,我得到正確的輸出。

+0

你是否在程序中以某種方式聲明函數?我的程序仍然沒有認識到這個功能。我在第二次編輯中添加了一個不起作用的示例代碼。 – Nordico

+0

@Nordico我更新了答案,不適合在評論框中。 – milancurcic

+0

好的。儘管這樣做不需要將東西放在模塊中並且有很多.mod文件,但我仍然必須在所有程序中指定我將事先使用哪些函數(只有我將它們聲明爲變量而不是使用「USE」適當的mod)。它確實好得多,但我想知道是否有一種方法可以像調用任何固有的fortran函數一樣調用我的函數:通過調用該命令,不必做任何以前的聲明(只需將庫鏈接到編譯時間)。 – Nordico

7

我的建議是將你的函數和子程序放入一個模塊,然後使用該模塊。將邏輯上相關的那些放入同一個模塊中。每個程序使用一個模塊似乎非常不方便 - 爲什麼你更喜歡這種方法?將過程(函數和子例程)放入模塊然後「使用」該模塊的原因是它使接口「顯式」,以便編譯器可以檢查調用中的實際參數與過程的僞參數之間的一致性。這會發現許多類型的錯誤,並節省您的編程工作量。與編寫聲明(「界面」)相比,這很容易和自動化。您不必編寫過程聲明和界面,並且在進行修改時不必保持一致。是的,「調用」語句幫助編譯器識別子例程,但通過模塊使接口顯式的優勢需要模塊用於函數和子例程。

編輯回答評論:是的,即使程序被放入一個庫,我會把它們放到一個單一的模塊。如果程序完全不相關,那麼它們可能屬於單獨的庫和單獨的模塊。如果相關,那麼在同一個庫和相同的模塊中。 Fortran提供了一些功能來管理同一模塊中有許多過程的可能「問題」:您可以明確在「使用」語句中使用哪些過程,並通過使用「僅」條款避免名稱衝突,僅列出過程被使用。如果默認名稱與其他名稱衝突,您甚至可以重命名要使用的過程。

+0

即使代碼是用於圖書館的?在這種情況下讓所有的程序分離,這樣更容易處理它們嗎? (除了相同過程的不同版本,例如重載的版本)是不是一個庫已經被認爲是邏輯相關過程的彙編,如果是這樣,有模塊不會是多餘的?你把你的庫分成多個模塊嗎?我問,因爲我坦白地忽略哪種方法是最好的做法,爲什麼... – Nordico

+0

(哦,我顯然不喜歡有很多單一的程序模塊;這就是爲什麼我問這裏是否有一個不需要將它們包含在模塊中的方式= P我也不知道在模塊內部而不是在模塊外部有任何優勢,除了以這種方式放置某些過程會導致錯誤的情況之外) – Nordico

+0

但是用單個過程文件來創建庫不是更好嗎?特別是如果你有一個有很多程序的圖書館;當你想修改或添加一些內容時,將它們全部放在同一個文件中不會有點難以置信?或者你認爲每個圖書館只有很少的程序通常會更好?或者有什麼方法可以將程序的代碼保存在不同的文件中,並仍然將它們「包含」在一個模塊中? – Nordico

0

要回答有關函數和子例程與隱式接口之間的區別的問題:函數的用法與變量類似,並且需要知道類型,因此您需要使用外部屬性聲明它們。 但是,我也強烈建議M. S. B.s的答案,你應該把所有東西都放到模塊中,通過這個你可以爲你的所有例程獲得明確的接口,並且避免了這些問題。還有一點評論,你的示例代碼中的return語句是不必要的,以及停止。