作者callmei (挨)
看板MATLAB
标题[心得] 在FORTRAN呼叫MATLAB的函数(64位元)
时间Sat May 14 22:40:59 2011
前言:(都是废话~可以跳过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
※ 编辑: callmei 来自: 140.112.46.73 (05/14 22:41)
1F:推 kobenein:推 之前用MATLAB写一个程式 跑起来太慢 就打算核心部分 05/15 00:16
2F:→ kobenein:用FORTRAN来写 不过搞FORTRAN COMPILER搞好久 05/15 00:16
3F:→ kobenein:我就投靠C了 PS本来不会C 为了写MEX档才学的 05/15 00:17
4F:→ kobenein:本来是学FORTRAN 05/15 00:17
5F:推 imys:大推 回去试试看 谢谢分享! 05/15 00:48
6F:推 lenakaho:推~好棒!! 05/15 19:17
7F:→ JUSTNONE:各有优点吧 要速度 我可能也不会用MATLAB...... 05/17 12:02
8F:→ JUSTNONE:写了海上路径自动规划 台湾到非洲跑了10分钟 = = 05/17 12:02