文档库 最新最全的文档下载
当前位置:文档库 › FORTRAN调用MATLAB

FORTRAN调用MATLAB

*************************************************
* *
* 一、Visual Fortran中使用Matlab引擎 *
* *
*************************************************

source:https://www.wendangku.net/doc/d415584613.html,/cgi-bin/ut/topic_show.cgi?id=16634&h=1&bpg=1&age=-1

#1.安装
软件版本:
Compaq Visual Fortran(以下简称CVF)6.5
Matlab 6.1
安装路径:
CVF: C:\Program Files\Microsoft Visual Studio
Matlab: D:\matlab
#2.配置mex
在matlab下运行命令mex –setup,然后按提示选择CVF编译器
#3.配置编译环境
有两种选择
(1)Matlab下编译
(假设matlab安装目录为 %matlab%)
1.打开%matlab%\bin\win32\mexopts\df60engmatopts.bat
将13行中的 set DF_ROOT=%DF_ROOT %
改为set DF_ROOT =C:\Program Files\Microsoft Visual Studio (CVF安装目录)
2.将matlab的工作目录改为你的fortran源代码存放的目录
3.在matlab下运行 mex –f df60engmatopts.bat exsample.for
(假设源文件为exsample.for 其中有关于matlab引擎的操作)
(2)CVF下编译
1.新建一个项目
2.在tools->directory 里设置 include 和 lib目录
记住要包括以下目录
include ->C:\Program Files\Microsoft Visual Studio\DF98\Include
include->C:\Program Files\Microsoft Visual Studio\DF98\IMSL\Include
include->D:\MATLAB\EXTERN\INCLUDE

lib->D:\MATLAB\EXTERN\LIB\WIN32
lib->D:\MATLAB\EXTERN\LIB\WIN32\DIGITAL\DF60
lib->C:\Program Files\Microsoft Visual Studio\DF98\IMSL\Lib
lib->C:\Program Files\Microsoft Visual Studio\DF98\Lib
3. 在project->setting->link->Object/library modules里添加libmx.lib libmat.
lib libeng.lib

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

1。上面提到的无法定位程序输入点 的错误。
因为我是用的matlab自带的一个例程,出现这个错误肯定是自己系统的问题。不知道别人有没有遇到过。在这里发问,没结果呀。我就用“无法定位程序输入点”在“百度”上搜,查到一个mm在玩某个游戏的时候也遇到这样错误,解决的办法就是把提到的那个dll文件名前加_,如libeng.dll改为_libeng.dll,照这样按照出错提示把c:\winnt\system32中的libeng.dll、libmx.dll、libut.dll都改了一遍,再编译运行,搞定。
2。我要做的其实是想借Matlab中的用符号运算解一个二元三次方程组来求八节点等参单元中给定点整体坐标对应的局部坐标。主要就是根据matlab中的fengdemo.f来加入自己的东西,其实也很简单,一些小的地方要注意。开始的时候老是编译不通过,一度都要放弃了,因为用到Symbolic Math Toolbox中的solve,以为不支持。偶尔看fengdemo.f的源程序,在用到engEvalString时输入到matlab中的单引号(')都是用2个单引号('')来表示的,错就在这里,统统改掉,就可以了。
Matlab中的计算结果: 0.99433792247939 0.92631964961160
Fortran中调用结果: 0.99433789751

5527 0.926319366356284
差一点,双精度的
3。我的源程序
! XSHHN 2004.6.22
program main
double precision ElementCod(16),InquireCod(2),LocalCod(2)
DATA ElementCod/-6.75000E+00,-6.75000E+00,-6.2500,-6.25000E+00,&
& -6.75000E+00,-6.50000E+00,-6.25000E+00,-6.50000E+00,&
& 1.00000E+01,9.50000E+00,9.50000E+00,1.00000E+01,&
& 9.75000E+00,9.50000E+00,9.75000E+00,1.00000E+01/ !一组八节点单元节点坐标
data InquireCod/-6.3,9.55/ !需查询的单元内整体坐标
data LocalCod/2*0/ !查询到的单元内局部坐标
call InquireLocalCod(ElementCod,InquireCod,LocalCod)
write(*,*)LocalCod
end
!调用MATLAB查询局部坐标的子程序
subroutine InquireLocalCod(ElementCod,InquireCod,LocalCod)
double precision ElementCod(16),InquireCod(2),LocalCod(2)
integer engOpen,engGetVariable,mxCreateDoubleMatrix
integer engPutVariable, engEvalString, engClose
integer mxGetPr
integer ep,EC,IC,LC
integer status
write(*,*)ElementCod,InquireCod,LocalCod
ep=engOpen('matlab') !打开Matlab引擎
if (ep.eq.0) then
write(6,*)'Can''t start MATLAB engine'
stop
endif
EC=mxCreateDoubleMatrix(1,16,0) !建立mxArray
call mxCopyReal8ToPtr(ElementCod,mxGetPr(EC),16)
IC=mxCreateDoubleMatrix(1,2,0)
call mxCopyReal8ToPtr(InquireCod,mxGetPr(IC),2)
status = engPutVariable(ep,'EC',EC) !将mxArray送入Matlab
if (status.ne.0) then
write(6,*)'engPutVariable failed1'
stop
endif
status=engPutVariable(ep,'IC',IC) !将mxArray送入Matlab
if (status.ne.0) then
write(6,*)'engPutVariable failed2'
stop
endif
if (engEvalString(ep, 'syms r s;') .ne. 0) then !在这里就开始调用Symbolic Math Toolbox了
write(6,*) 'engEvalString failed3'
stop
endif
!下面开始向Matlab中输入8节点等参单元的形函数,注意在Matlab中的“'”要表示成“''”
mmm=engEvalString(ep,'N1=sym(''(1-r)*(1-s)*(-r-s-1)/4'')')
mmm=engEvalString(ep,'N2=sym(''(1+r)*(1-s)*(r-s-1)/4'')')
mmm=engEvalString(ep, 'N3=sym(''(1+r)*(1+s)*(r+s-1)/4'')')
mmm=engEvalString(ep, 'N4=sym(''(1-r)*(1+s)*(-r+s-1)/4'')')
mmm=engEvalString(ep, 'N5=sym(''(1-r^2)*(1-s)/2'')')
mmm=engEvalString(ep, 'N6=sym(''(1+r)*(1-s^2)/2'')')
mmm=engEvalString(ep, 'N7=sym(''(1-r^2)*(1+s)/2'')')
mmm=engEvalString(ep, 'N8=sym(''(1-r)*(1+s^2)/2'')')
mmm=engEvalString(ep, 'x=0')
mmm=engEvalString(ep, 'y=0')
mmm=engEvalString(ep, 'x=x+N1*EC(1)+N2*EC(2)+N3*EC(3)+N4*EC(4)')
mmm=engEvalString(ep, 'x=x+N5*EC(5)+N6*EC(6)+N7*EC(7)+N8*EC(8)')
mmm=engEvalString(ep, 'y=y+N1*EC(9)+N2*EC(10)+N3*EC(11)+N4*EC(12)')
mmm=engEvalString(ep, 'y=y+N5*EC(13)+N6*EC(14)+N7*EC(15)+N8*EC(16)')
mmm=engEvalString(ep, 'x=x-IC(1)')
mmm=engEvalString(ep, 'y=y-IC(2)')
mmm=engEvalString(ep, '[r,s]=solve(x,y)') !这里是最关键的,就是用solve解方程啊
mmm=engEvalString(ep, 'LC=[eval(r(1)) eval(s(1))]')
LC=engGetVariable(ep,'LC')
call m

xCopyPtrToReal8(mxGetPr(LC), LocalCod, 2)
write(*,*)LocalCod !看看结果

call mxDestroyArray(EC) !回收内存
call mxDestroyArray(IC)
call mxDestroyArray(LC)
status = engClose(ep) !关闭Matlab引擎
if (status .ne. 0) then
write(6,*) 'engClose failed'
stop
endif
end






发现了一遍文章是介绍这方面内容的,但我按照它的例子没有编译过去
请指点一下吧
……………………………………………………………………………………

如何由Fortran中呼叫MATLAB的M檔案
如何由Fortran中呼叫MATLAB的M檔案
基本的作法是先將M檔案轉換為.dll檔
再由Fortran去呼叫之

程式是使用 Matlab 6.5.1
Matlab compiler v3.0.1
Compaq Visual Fortran Pro v6.6.0 (CVF) (Compaq bought DEC and HP bought Compaq)

原始m檔案為

function b= matlabinc(a)
% Increment given argument a and return result b to caller, displaying both on screen as well
disp(a)
explore(a)
b = a + 1;
disp(b)
explore(b)

使用以下的方式compile 為DLL
eval(['mcc -t -L C -W lib:QuGeneLib -T link:lib -h ' progName '.m libmmfile.mlib'])

%如果m 檔案中有繪圖請使用以下方式
%eval(['mcc -B sgl -t -L C -W libhg:QuGeneLib -T link:lib -h ' progName '.m libmmfile.mlib'])

以下為原始檔與描述
This heavily commented Fortran program serves as a simple example on how a MATLAB .m file can be called from Fortran. Suitable if this is your first time trying this.

The basic mechanism is to pack the C-compiled .m into a .dll and link to it from Fortran. Argument and result xfer mechanism is explained so that program can be easily expanded.

程式開始
以下藍色部分為MATLAB中使用方式
藍色以下部分為Fortran中使用方式

program test

!===============================================================================================================
!
! This program serves as a simple example on how to interface a Fortran program to Matlab,
! not the other way round which is well documented elsewhere.
!
!
! ENVIRONMENT
! This will work using the following environment on a Windows XPpro PC, other environments have not been tested
! but may work as well.
!
! * Matlab v6.5.1 R13 SP1
! * Matlab compiler v3.0.1
! * Compaq Visual Fortran Pro v6.6.0 (CVF) (Compaq bought DEC and HP bought Compaq)
!
!
! OVERVIEW
! We start with a simple .m script and create C-code from it, which is then compiled and placed into a .dll.
! This process is performed fairly automatic in the Matlab environment.
!
! Now we write a Fortran program that calls this Matlab routine. For this to work properly we have to setup
! Matlab structures containing the data values (the mx array and pointers to it), take care of the underscores
! added to routine names in dll's, the way the arguments are referenced because the routine was generated
!

from C-code and the fact that the routine resides in a dll. All this need only be done for the Matlab script
! we create, we may call any mx* routines in a normal Fortran fashion. All this is described in detail now.
!
!
! DETAIL
! Our task is to call the following Matlab script from a Fortran program.
!
! function b = matlabinc(a)
! % Increment given argument a and return result b to caller, displaying both on screen as well
! disp(a)
! explore(a)
! b = a + 1;
! disp(b)
! explore(b)
!
! We compile our Matlab script using a function like this
!
! function compileDLL(progName)
! % Compile the .m file given and place result into a dll
! eval(['mcc -t -L C -W lib:QuGeneLib -T link:lib -h ' progName '.m libmmfile.mlib'])
! % Use this line instead if you call graphics routines in your .m file
! %eval(['mcc -B sgl -t -L C -W libhg:QuGeneLib -T link:lib -h ' progName '.m libmmfile.mlib'])
!
! This will create two files, QuGeneLib.lib and QuGeneLib.dll. The.lib file contains information for the Fortran
! compiler on what is in the .dll file. The .dll is the dynamic link library that contains our compiled Matlab
! routine. Copy both to the Fortran development directory were the .f90 files live. Also copy all Matlab .dll's
! you are using to the same location, libmx.dll is one you will definitely need. If you call graphics routines
! you will also need sgl.dll and you have to place FigureMenuBar.fig and FigureToolBar.fig into the path of
! the executing Fortran program as well.
!
! In CVF use "project->add to project->files" and pick the QuGeneLib.lib file. Read through the comments in this
! Fortran program to understand how everything works. You can use the DOS command
!
! dumpbin/exports libmx.lib
!
! or the Windows Dependency Walker
!!https://www.wendangku.net/doc/d415584613.html,/
!
! to see the names of the routines included in the corresponding .dll, this is what has to go into the
! ALIAS directive when defining the interface for the C routine in the dll with the !DEC$ compiler statement.
! You will note an added underscore and sometimes also a @number after the name. The number indicates the number
! of bytes used for arguments. Also, C is case sensitive so cases in routine names must match.
!
! Note: You do not need to do this for any mx* routines, Matlab has defined an API for all of these. Although you will
! encounter a name such as MXCOPYPTRTOREAL8@12 in libmx.lib, you have to call mxCopyPtrToReal8 instead.
!
! The main way of achieving data transfer between Fortran and the Matlab C program created from our .m file script
! is via the mx routines supplied by Matlab in the libmx.dll. Read through Matlab HELP titled
! "External Interfaces/API Reference: Fortran MX-Functions" before expanding this example.
!
! Note: You do not need to define any interfaces, pointers etc for the mx* routines. You do also not need
! to call loadlibrary or getprocaddress for the

mx* routines. It will not work if you do any of this.
!
!
! Alex Pudmenzky, 24 September 2003, The University of Queensland, Brisbane, Australia (https://www.wendangku.net/doc/d415584613.html,).!
!===============================================================================================================
! Declaration section

! Definitions for the "loadlibrary", "freelibrary" and "getprocaddress" routines are included in the following files
!use dfwin ! More stuff than is in kernel32
use kernel32 ! Use this to safe compilation time if other stuff is not needed

IMPLICIT NONE ! Produce error during compilation if variables aren't declared

!---------------------------------------------------------------------------------------------------------------
INTERFACE

! Define the interfaces to our own Matlab scripts
! The LibInitialize() and LibTerminate() routines are automatically added by the compilation
! and dll creation progress in Matlab.
SUBROUTINE matlabinc(nlhs,plhs, nrhs,prhs)
integer*4 :: nlhs,nrhs
integer*4 :: plhs(*),prhs(*)
!DEC$ ATTRIBUTES C, DLLIMPORT, ALIAS:"_mlxMatlabinc" :: matlabinc
!DEC$ ATTRIBUTES VALUE :: nlhs,nrhs
!DEC$ ATTRIBUTES REFERENCE :: plhs,prhs
END SUBROUTINE

SUBROUTINE QuGeneLibInitialize()
!DEC$ ATTRIBUTES C, DLLIMPORT, ALIAS:"_QuGeneLibInitialize" :: QuGeneLibInitialize
END SUBROUTINE

SUBROUTINE QuGeneLibTerminate()
!DEC$ ATTRIBUTES C, DLLIMPORT, ALIAS:"_QuGeneLibTerminate" :: QuGeneLibTerminate
END SUBROUTINE

END INTERFACE

!---------------------------------------------------------------------------------------------------------------
! This part only required for our own Matlab routine, not the mx* routines
integer :: p_QuGeneLib_dummy, p_libmx_dummy
logical :: status

! QuGeneLib.dll
pointer (p_QuGeneLib,p_QuGeneLib_dummy)
pointer (pr1_QuGeneLib,QuGeneLibInitialize)
pointer (pr2_QuGeneLib,matlabinc)
pointer (pr3_QuGeneLib,QuGeneLibTerminate)

!---------------------------------------------------------------------------------------------------------------
! Declare all mx* routines we call
INTEGER*4 :: mxGetData !
INTEGER*4 :: mxGetNumberOfElements !
INTEGER*4 :: mxCreateScalarDouble !
INTEGER*4 :: mxCreateNumericMatrix !
INTEGER*4 :: mxClassIDFromClassName !

!---------------------------------------------------------------------------------------------------------------
real*8 :: a(3) ! What I store in Matlab mx array
real*8 :: b(3) ! What I read out of Matlab mx array
integer*4 :: a_mx_p ! Pointer to mx array for a
integer*4 :: a_dx_p ! Pointer to data in mx array for a
integer*4 :: b_mx_p ! Pointer to mx array for b
integer*4 :: b_dx_p ! Pointer to data in mx array for b
integer*4 :: na ! Number of entries in a
integer*4 :: nb ! Number of entries in b

!===============================================================================================================
! Executable section

!

Locate the QuGeneLib.dll and load it into memory
! This library contains all of our own Matlab functions
p_QuGeneLib = loadlibrary("QuGeneLib.dll"C)
if (p_QuGeneLib == 0) then
type *, "Error occurred opening QuGeneLib.dll"
type *, "Program aborting"
goto 1000
endif

! Set up a pointers to the routines of interest
pr1_QuGeneLib = getprocaddress(p_QuGeneLib, "_QuGeneLibInitialize"C)
if (pr1_QuGeneLib == 0) then
type *, "Error occurred finding _QuGeneLibInitialize in QuGeneLib.dll"
type *, "Program aborting"
goto 1000
endif

pr2_QuGeneLib = getprocaddress(p_QuGeneLib, "_mlxMatlabinc"C)
if (pr2_QuGeneLib == 0) then
type *, "Error occurred finding _mlxMatlabinc in QuGeneLib.dll"
type *, "Program aborting"
goto 1000
endif

pr3_QuGeneLib = getprocaddress(p_QuGeneLib, "_QuGeneLibTerminate"C)
if (pr3_QuGeneLib == 0) then
type *, "Error occurred finding _QuGeneLibTerminate in QuGeneLib.dll"
type *, "Program aborting"
goto 1000
endif

!===============================================================================================================
! Initialise interface to our Matlab routine
! (this initialisation routine is automatically created by Matlab during compilation)
call QuGeneLibInitialize()

! The real*4 value we want to pass from this Fortran code to our Matlab routine
a(1) = 1.0
a(2) = 2.0
a(3) = 3.0

! Create mx array for this value and remember pointer to that mx array (not the value!)
! The mx Array is a special structure that can contain any Matlab datatype
! We omit checking pointers from here on to preserve simplicity, if they are returned zero the operation failed
!a_mx_p = mxCreateScalarDouble(a)
a_mx_p = mxCreateNumericMatrix(3, 1, mxClassIDFromClassName('double'), 0)

! Remember pointer to the data in the mx array, given the pointer to the mx array itself
a_dx_p = mxGetData(a_mx_p)

type *, a
! Store data in Matlab mx array
call mxCopyReal8ToPtr(a, a_dx_p, 3)

! Now we want to prove the data above has been stored by retrieving it again

! Retrieve the number of values (elements) in the mx array, given the pointer to the mx array (not the value!)
na = mxGetNumberOfElements(a_mx_p)

! Check
type *, na

! Now call our Matlab routine which returns b given the argument a (actually pointers to a & b)
call matlabinc(1,b_mx_p, 1,a_mx_p)

! Retrieve data pointer given the mx array pointer
b_dx_p = mxGetData(b_mx_p)

! Convert the value(s) stored in the mx array to Fortran representation, given the pointer to the data in the mx array
call mxCopyPtrToReal8(b_dx_p, b, 3)

! Just to see if it worked
type *, b

! Release memory
call mxDestroyArray(a_mx_p)
call mxDestroyArray(b_mx_p)

! Terminate interface to our Matlab routine
! (this termination routine is automatically created by Matlab during compilation)
call QuGeneLibTerminate()

1000 continue

! Release library
status =

freelibrary(p_QuGeneLib)

end

大家可以參考一下


相关文档
相关文档 最新文档