Fortran Coder

标题: fortran 调用 matlab 函数 [打印本页]

作者: 一路向北    时间: 2021-10-17 16:16
标题: fortran 调用 matlab 函数
请问如何在fortran中调用matlab 函数, 有详细教程吗?
如果有的话请联系我,谢谢

作者: li913    时间: 2021-10-17 18:11
http://fcode.cn/guide-125-1.html
作者: 一路向北    时间: 2021-10-17 19:18
[Fortran] 纯文本查看 复制代码
module matlab
implicit none

integer ep !指针,用于指向打开的matlab
integer status !非指针,记录命令执行的结果是否有效

integer,external::engOpen,engPutVariable,engGetVariable,engEvalString,engClose
integer,external::mxCreateDoubleMatrix,mxGetPr

contains
!!======================================
!!打开matlab应用程序
subroutine startmatlab()
implicit none
write(*,*)"正在打开matlab应用程序,请稍后......."
ep = engOpen('matlab')
if(ep==0)then
write(*,*)"未能打开matlab应用程序,程序结束"
stop
else
write(*,*)"成功打开matlab应用程序窗口"
endif
endsubroutine startmatlab
!!===================================
!!关闭matlab应用程序
subroutine closematlab()
implicit none
write(*,*)"正在关闭matlab窗口,请稍后......"
status = engClose(ep)
if(status /=0 )then
write(*,*)"未能关闭matlab程序窗口,程序结束"
stop
else
write(*,*)"成功关闭matlab的程序窗口"
endif
endsubroutine closematlab
!!========================================
!!在matlab中执行命令
subroutine mc(string)
implicit none
character(*) string
print *,"正在matlab中计算语句: ",string
if(engEvalString(ep,string) /=0 )then
!!!engEvalString发送命令让 Matlab 执行,参数 ep 为函数 engOpen 返回的引擎指针,字符串 string 为要 matlab 执行的命令。
write(6,*) 'engEvalString failed'
stop
endif
endsubroutine mc
!!==========================================
!!将fortran中的矩阵送到matlab中去
subroutine f2m(fdata,mstring,row,col)
implicit none
integer row,col
real(8) fdata(1:row,1:col)
character(*)mstring
integer ptemp
ptemp = mxCreateDoubleMatrix(row,col,0) !!!mxCreatDoubleMatrix新建一个double 类型数组
if(ptemp==0)then
write(*,*)"无法申请内存"
stop
endif

call mxCopyReal8ToPtr(fdata,mxGetPr(ptemp),row*col)
!!!mxCopyReal8ToPtr将一个Fortran语言的实数类型数组中的数据复制到某个阵列的实数部分或虚数部分中。
!!!fdata为fortran语言的实数类型数组
!!!mxGetPr(ptemp)为指向某个阵列的实数或虚数部分的数据的指针;mxGetPr用来获取矩阵指针
!!!row*col为希望复制的元素的个数
status = engPutVariable(ep,mstring,ptemp) !!!向 Matlab 引擎工作空间写入变量。
call mxDestroyArray(ptemp) !!!释放内存

print *,"正在matlab中生成矩阵: ",mstring

if(status /= 0)then !!成功返回0
write(*,*) 'engPutVariable failed'
stop
endif
endsubroutine f2m
!!==============================================
!!将matlab中的矩阵输入到Fortran中
subroutine m2f(mstring,ddata,row,col)
integer row,col
real(8) ddata(row,col)
character(*)mstring

integer ptemp
ptemp = engGetVariable(ep,mstring) !!!获得当前 Matlab 窗口的显示 / 隐藏情况,可以调用函数:
call mxCopyPtrToReal8(mxGetPr(ptemp),ddata,row*col)
endsubroutine m2f

endmodule matlab      
      
Program main
use matlab
        implicit none
        integer,parameter :: ndata=10
        real(8)::x(ndata),y(ndata),z(ndata)
        integer::m

do m=1,ndata
        x(m)=3.1415926587*(m-1)/(ndata-1)
        y(m)=sin(x(m))
end do
call startmatlab()
call f2m(x,"x",1,ndata)
call f2m(y,"y",1,ndata)
call mc("plot(x,y);title('y=sin(x)');xlabel('x');ylabel('y')")
call mc("z=2*y")
call m2f("z",z,1,ndata)

print *,"     x     ","      y       ","        z            ","   2*y"
do m=1,ndata
        write(*,"(G15.6,G15.6,G15.6,G15.6)")  x(m),y(m),z(m),2*y(m)
enddo

pause
end Program main

作者: 一路向北    时间: 2021-10-17 19:27

请问为什么会出现这个错误啊?
代码在上面,有大神可以帮我看下吗谢谢

Snipaste_2021-10-17_19-26-14.jpg (647.07 KB, 下载次数: 303)

请问为什么会出现这个错误啊? 代码在上面,有大神可以帮我看下吗谢谢

请问为什么会出现这个错误啊? 代码在上面,有大神可以帮我看下吗谢谢

作者: fcode    时间: 2021-10-17 22:41
因为你用的64位 Fortran,所以你应该用
integer(8),external::engOpen,engPutVariable,engGetVariable,engEvalString,engClose
integer(8) , external :: mxCreateDoubleMatrix,mxGetPr
代替
integer,external::engOpen,engPutVariable,engGetVariable,engEvalString,engClose
integer,external::mxCreateDoubleMatrix,mxGetPr

同样的还有:
integer(8) ep !指针,用于指向打开的matlab
integer(8) ptemp

凡是 Matlab 返回指针的,都应该用 integer(8) 才对。

我记得有个 include "fintrf.h" 文件,里面定义了 mwPointer 这个东西。在64位时自动为integer(8),在32位时自动为 integer
这样,你就可以不必考虑是32位还是64位了。

作者: zfx    时间: 2022-3-3 16:33
一路向北 发表于 2021-10-17 19:27
请问为什么会出现这个错误啊?
代码在上面,有大神可以帮我看下吗谢谢
...

请问楼主问题解决了嘛
作者: tiancYao    时间: 2023-6-26 14:59
fcode 发表于 2021-10-17 22:41
因为你用的64位 Fortran,所以你应该用
integer(8),external::engOpen,engPutVariable,engGetVariable,engE ...

大佬你好,我刚接触Fortran,这周在尝试接触fortran和matlab混合编程,我也遇到了论坛里其他同学遇到的问题,即在fortran中定义engine api的相关函数时integer位数定义的问题,困扰了我半天,通过您的帖子找到答案,十分欣喜,万分感谢!

作者: tiancYao    时间: 2023-6-26 15:11
tiancYao 发表于 2023-6-26 14:59
大佬你好,我刚接触Fortran,这周在尝试接触fortran和matlab混合编程,我也遇到了论坛里其他同学遇到的问 ...

engOpen和engEvalString后我发现matlab新打开的小窗口里并不会出现我用engValString输给matlab的指令,尽管engValString返回的值非0,应该是传递成功了。但是matlab小窗中没有显示我给他的命令,也没有出现我希望的画图窗口。您知道是为什么嘛?
作者: cvlb    时间: 2024-3-13 14:37
fcode 发表于 2021-10-17 22:41
因为你用的64位 Fortran,所以你应该用
integer(8),external::engOpen,engPutVariable,engGetVariable,engE ...

感谢!感谢!感谢!感谢!感谢!




欢迎光临 Fortran Coder (http://bbs.fcode.cn/) Powered by Discuz! X3.2