[心得] 在FORTRAN呼叫MATLAB的函數(64位元)
前言:(都是廢話~可以跳過XD)
MATLAB提供了向外窗口給C語言及FORTRAN語言,使得這兩種語言可以直接調動MATLAB的函
數來使用,C/MATLAB混編的教學很多,但關於FORTRAN/MATLAB,台灣用FORTRAN的本來就
少,而專精FORTRAN的人也有他們自己的一套系統,譬如TecPlot以及很多免費的FORTRAN
繪圖函數庫,所以其實真正有教怎麼用FORTRAN呼叫MATLAB函數的中文教學很少,尤其是
針對不同編譯器的設定上,最常找到的教學是CVF編譯32位元程式的設定,而IVF幾乎沒有
中文的,英文的又閱讀的很辛苦。MATLAB雖然有內建FORTRAN呼叫MATLAB的範例程式碼,
但是那是使用FORTRAN77寫成的。
也許很懂程式設計的人不用什麼教學就知道該怎麼設定,但是我想還是有很多研究生跟
我一樣上研究所才開始學程式,所以除了會寫CODE外,很多關於編譯器方面該怎麼設定也
都一知半解,尤其現在IVF跟經典教科書使用的CVF已經長得不太一樣了,所以我終於成功
能夠在FORTRAN程式呼叫MATLAB的一些函數後,想說放到網路上讓有需要使用到MATLAB及
FORTRAN的苦命菸酒生們參考如何設定。
其實大部分都是網路上東蒐集一點西蒐集一點最後整理出來的東西,而我主要是針對如何
設定及一些該注意的地方來分享,至於詳細的語法,我想有空再說吧,而且語法方面其實
都是由MATLAB提供的,所以可以參考C怎麼呼叫MATLAB函數。或是GOOGLE '調用MATLAB計
算引擎',也可以找到關於語法上的介紹。
編譯一個有呼叫到MATLAB的FORTRAN原始碼有兩種方法:
(MATLAB跟FORTRAN編譯器都必須安裝)
1.使用MATLAB編譯,這個最簡單,幾乎不用設定,但是MATLAB只能懂FIX格式(77)的
FORTRAN,要讀FREE格式的,必須要在某個.bat檔裡面去修改,在此不去說明,因為
我想應該也沒人用FORTRAN寫了一個程式後還特地使用MATLAB編譯吧...
(這方法需要MATLAB能辨別出使用的FORTRAN編譯器,但似乎MATLAB只認識CVF跟IVF,
其他如PGI等等其他廠牌編譯器他都不認得)
2.使用FORTRAN的編譯器去編譯,我想菸酒生們大部分應該都是使用WINDOW系統,所以下
面講的也是這個方法。會用LINUX的人都是專業的,我想應該他們都會這些了~囧
3.把MATLAB的函式庫編譯成.dll,不過這太專業了,實際上怎麼做我也不懂,我只知道
這方法可以讓程式在沒安裝MATLAB的電腦上執行。
正文:
首先是我的操作環境,我想如果操作環境不同,可能也會有些不同,所以有可以依照操
作環境不同來調整設定方式:
作業系統:Windows 7 64位元
MATLAB版本:R2010a 64位元
安裝路徑C:\Program Files\MATLAB\R2010a
FORTRAN編譯器:Intel Visual Fortran 11 使用IDE介面
IDE介面是用Microsoft Visual Studio 2008
編譯組態: Debug x64
前置作業:
1.設定Win7環境變數:
控制台->系統及安全性->系統->進階系統設定->環境變數
出現的頁面會有上下兩大區塊,在下方的系統變數區塊中的變數欄尋找PATH這
項,點選後按下方的編輯鈕,在變數值那欄應該已經有很多路徑了,在最後加
上";",然後再加上下面這個路徑
C:\Program Files\MATLAB\R2010a\bin\win64
一直按確定關掉所有頁面後,重新開機(一定要重新開機!)
(若程式可以編譯,但執行時卻會出現找不到XXX.dll,通常都這步驟的問題)
2.設置專案屬性:
開啟會使用到MATLAB計算引擎的FORTRAN專案,記得組態要改成x64,至於是
Debug或Release我想都沒差。
(若組態是win32,我不確定能不能呼叫64位元的MATLAB)
a.專案->屬性->FORTRAN->GENERAL,在Additional Include Directories那欄
填上C:\Program Files\MATLAB\R2010a\extern\include
b.專案->屬性->FORTRAN->PREPROCESSOR,在Preprocess Source Files那欄
選擇YES
(這步驟重要~我卡很久後才知道要做這步驟)
c.專案->屬性->LINKER->GENERAL,在Additional Library Directories那欄
填上C:\Program Files\MATLAB\R2010a\extern\lib\win64\microsoft
d.專案->屬性->LINKER->INPUT,在Additional Dependencies那一欄填上
libmx.lib libmat.lib libeng.lib
確定,關掉屬性視窗。
(對於a、c、d若是不想針對特定專案,而是所有專案都可以呼叫MATLAB,可從
工具->選項裡去設定,請自行找編譯器教學......)
3.在程式碼最開頭加上 #INCLUDE "fintrf.h"
4.接著就可以用MATLAB針對FORTRAN呼叫MATLAB計算引擎的一些特定函數來寫程
式,跟在C裡呼叫的方式差不多,我個人是覺得必須要有指標的觀念才行,才
比較好懂跟自行運用。
因為這篇主要是針對64位元作業系統及64位元程式的設定及需要注意的事項
,所以關於語法請自行參考MATLAB的說明。
以一個在FORTRAN程式呼叫MATLAB畫圖的程式碼為例,前面數字為行號:
(若要把行號也寫進程式碼的話,記得#INCLUDE "fintrf.h"這行不能加行號)
#INCLUDE "fintrf.h"
1 PROGRAM main
2 IMPLICIT NONE
3 INTEGER*8,EXTERNAL:: engOpen,engClose,mxCreateDoubleMatrix
4 INTEGER*8,EXTERNAL:: mxGetPr,engPutVariable,engEvalString
5 INTEGER*8::ep,T,status
6 INTEGER*8::i,j,k
7 REAL*8::nodes(2,400)
8 DO i=1,400
9 nodes(1,i)=2d0*3.1415926/400d0*DBLE(i)
10 ENDDO
11 CALL RANDOM_SEED()
12 CALL RANDOM_NUMBER( nodes(2,:) )
13 nodes(2,:)=nodes(2,:)*2d0-1d0
14 i=2
15 j=400
16 k=0
17 ep=engOpen(' ')
18 T=mxCreateDoubleMatrix(i,j,k)
19 CALL mxCopyReal8toPtr(nodes,mxGetPr(T),2*400)
20 status=engPutVariable(ep,'voronoi_nodes',T)
21 status=engEvalString(ep,'for i=1:1:400, &
plot(voronoi_nodes(1,i),voronoi_nodes(2,i),''*''); &
hold on; &
end')
22 status=engEvalString(ep,'axis equal')
23 status=engEvalString(ep,'axis([0,2*3.1415926,-1.1,1.1])')
24 CALL mxDestroyArray(T)
25 PAUSE '按任意鍵結束'
26 status = engClose(ep)
27 END PROGRAM main
如果程式碼正確執行,應該會出現一張用MATLAB畫的圖,上面很多*號....
如圖http://ppt.cc/Jbsq
注意:
1.在64位元下,MATLAB的整數是8 bytes的資料型態,所以第3、4、5行可以看到
他們被宣告成8 bytes整數,第3、4行是呼叫MATLAB以及與MATLAB做資料交換
要用到的MATLAB引擎函數,簡單說就是FORTRAN與MATLAB溝通的橋樑,功能請自
行參考MATLAB的HELP,而第5行雖然不是宣告成指標變數,但其實它們的功用很
類似於指標。
2.(這點是我自己猜測的) 有些MATLAB的引擎函數是類似於傳址型態,而不能傳
值,所以像第18行的T=mxCreateDoubleMatrix(i,j,k),功能是在記憶體中
ALLOCATE一塊空間用來存放2*400的陣列,而k=0則表示此陣列都是純實數。
理論上應該寫成T=mxCreateDoubleMatrix(2,400,0)也可以(一些C語言的範例
好像也是這樣寫),但實際上會發現無法ALLOCATE,無法ALLOCATE時T會回傳0
,所以要先令i=2,j=400,k=0,然後寫成T=mxCreateDoubleMatrix(i,j,k)才
能ALLOCATE成功。原因只是我自己的猜測,真正的原因我也不清楚。總之遇到
這種MATLAB引擎指令可用回傳的值為多少來判斷是否執行成功,若執行成功,
回傳的為一個非0值,因為回傳的是類似於記憶體位置的資料(指標),若執行
失敗,會回傳0,可以依此點來判斷MATLAB引擎指令有沒有成功被執行。
3.為了避免混亂,所以我沒加上判斷MATLAB指令是否成功執行的語句。
4.有時候雖然成功執行指令,但其實只是說成功把東西從FORTRAN傳送到MATLAB
,而MATLAB那邊若是語法錯誤,FORTRAN這邊卻不會知道(不像直接操作
MATLAB時,若語法錯誤會出現錯誤訊息),所以跑出來的結果不一定會正確。
以上,以後畫圖就不用再另外輸出數據,然後再打開MATLAB讀入數據來畫了
除了畫圖外,我想MATLAB還有很多東西可以被FORTRAN拿來使用
像我研究這個也不是因為要畫圖,其實我是要使用MATLAB內建的建Delaunay三角形的函數
因為FORTRAN的建Delaunay三角形程式碼都是外國人寫的,使用教學都英文,根本看不懂
怎麼用,所以我才會把主意打到MATLAB上。我想有些人應該跟我一樣,雖然FORTRAN資源
豐富,但是卻因為看不懂英文所以不會使用=..=
我不是專門玩程式的人,只是因為研究所需要才開始學寫程式
所以如果有什麼東西是本來就該知道的基礎知識而我不知道,請見諒>//////<
希望有多點人一起玩玩看,不要輸給C/C++了XDDDD
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.46.73
→
05/14 22:31, , 1F
05/14 22:31, 1F
推
05/14 22:45, , 2F
05/14 22:45, 2F
推
05/15 06:52, , 3F
05/15 06:52, 3F
影像處理我也不熟耶@@
我記得有看過文章是說MATLAB核心內建的功能都可以使用
但是有些是屬於那些工具箱的,不是MATLAB原本就有的,就不一定了
→
05/15 06:54, , 4F
05/15 06:54, 4F
→
05/15 08:57, , 5F
05/15 08:57, 5F
→
05/15 08:58, , 6F
05/15 08:58, 6F
推
05/15 13:42, , 7F
05/15 13:42, 7F
推
05/15 16:31, , 8F
05/15 16:31, 8F
推
05/15 18:58, , 9F
05/15 18:58, 9F
→
05/15 20:51, , 10F
05/15 20:51, 10F
推
05/16 00:46, , 11F
05/16 00:46, 11F
推
05/16 12:51, , 12F
05/16 12:51, 12F
推
05/16 13:12, , 13F
05/16 13:12, 13F
IMSL有的函數基本上還是使用IMSL會比較快
姑且不論同樣的數值方法,MATLAB和FORTRAN誰的內建函數算得較快
光是從FORTRAN程式開始呼叫MATLAB,到完全啟動MATLAB計算引擎,就需要一點時間了
然後還要在FORTRAM、MATLAB間傳遞參數,也需要多執行一些指令
所以如果數據交換量大、交換頻率高的話 ,時間上反而沒效率
簡單說就是FORTRAN跟MATLAB間的溝通會耗費掉一些時間,每次都要花個幾秒鐘之類的
當然,如果程式是只跑幾分鐘或一兩個小時就跑完的那種,
或是整個程式就只有呼叫MATLAB那一兩次,其實是不差那幾秒的
其實如果只是要數值分析的功能的話,基本上IMSL都有了...
※ 編輯: callmei 來自: 140.112.218.94 (05/17 05:26)
推
05/17 13:35, , 14F
05/17 13:35, 14F
Fortran 近期熱門文章
PTT數位生活區 即時熱門文章