阅读本文需要:想用/正在用MATLAB
本文读完后你将掌握:如何优雅地用NPP开发MATLAB
本文主要内容是我一天内学会的。
虽然面临的是完全不同的问题,但这个和上一期那个是同一系列的,都是踩过配置环境相关的坑。有点不同就是:上一期那个是纯粹老师要求,而这一期是我自己一直憋好久憋出来的。
简单交代下动机:MATLAB是用来做科学计算的,但和python这些不一样,本身MATLAB就是个庞然大物,集IDE、命令行、画图等功能于一身。只是这个IDE代码高亮和补全不是很满意,于是我决定用Notepad++(简称NPP)进行开发,然后在MATLAB本体里执行。
当然这不算是个大问题,不过总归是被我玩出点有意思的小花样,还是想秀一下操作。
(友情提示:正片在第2节)
0. 切屏
这个是相对而言是最没有技术含量的。就是开一个NPP写代码,一个MATLAB跑程序,仅此而已。用户体验相对比较差。如果是这么用的话,其实还不如直接在MATLAB自带的编辑器里面写……
(Tips:Win平台,ctrl+TAB是切屏快捷键,会提升一点用户体验)
1. NppExec运行命令行模式的MATLAB
虽然我认为这个不算是非常困难的操作,但是如果没有一些计算机的底子的话,可能发现不了。
MATLAB是可以用命令行模式运行的。这个是很关键的一个问题,因为MATLAB启动速度是比较感人的。比如我这里,直接启动MATLAB大概需要20秒左右的时间。但是,命令行模式运行的话,如果不开笨重的GUI,可以压缩到十秒以内。
在cmd下,运行matlab -h(默认matlab路径已经加入环境变量),可以看到参数列表。这一节感兴趣的是这几个参数:
差不多这样的,当然字体有点丑陋
上一期我们知道,NPP可以F5执行一条NPP指令。NPP指令可以认为约等于一条DOS指令,唯一不同是多了些内置指令(如NPP_SAVE,保存当前文件),和一些环境变量(如$(FULL_CURRENT_PATH)是当前完整路径,注意到这个和%cd%即cmd对环境变量的引用方式不同。)具体内容可以在NPP官方文档(http://docs.notepad-plus-plus.org/)查看。
但是F5只能执行一行指令的蛋疼编译方式还是有点撑不住,所以如果你在用NPP进行开发,郑重向你推荐NPP的插件NppExec,在插件-插件管理中找到即可下载。NppExec提供的F6执行可以运行多行代码,可以保存为脚本,还可以在控制台试命令,岂不美哉。
在知道这两件事之后,就可以用F6执行:
NPP_SAVE
matlab -nodesktop -nosplash -sd "$(CURRENT_DIRECTORY)" -r $(NAME_PART)
这样,每次执行后,就会多运行一个MATLAB进程,把代码跑出来。如果你把MATLAB当成一种编程语言来看,那么这种运行方式其实也足够简单了。一键编译运行,还要啥自行车?
只是,MATLAB打开速度还是太慢了(即使不开GUI,白等十几秒也是很难受的),另外,要去查看结果,还是要切到新打开的MATLAB上。如果我们能让MATLAB一直运行,然后在NPP上运行一段程序,给MATLAB一个信号,执行一段指令,再返回NPP,这样把MATLAB当成个服务器来用,全程不需要切出NPP,这样就好了。问题是,这能做到吗?
2. NppExec & MATLAB COM automation API
还真可以,假如你用的是WIndows的MATLAB。
WIndows平台提供所谓COM模型(组件对象模型)技术,可以解决程序间的通信问题。而COM automation是一种COM协议,功能是A程序调用操作B程序的组件。MATLAB恰好有提供这么一套协议的API,也就意味着我们可以用支持COM automation的程序来控制MATLAB(当然,反过来也可以让MATLAB控制Excel之类的程序)文档可以在这里找到:(https://ww2.mathworks.cn/help/matlab/call-matlab-com-automation-server.html?s_tid=CRUX_lftnav)
题外话:如果你看这个教程的相关链接,你会发现Python、Fortran、C/C++、Java等一系列MATLAB的API……Mathworks真是个不会拒绝任何来源的用户的公司呢
如果你已经试过了matlab -h,想必你已经发现了matlab -automation这个参数,它可以让matlab以命令行模式后台运行(当然你可以把它调到前台,看起来普通的-nodesktop没什么两样),同时开启服务器模式。
那么问题来了,我们要如何与MATLAB的COM控件通信呢?API给我们的解决方案就是:用支持COM控件的程序。具体来说,是.NET系的C#和VB。
我最终选择的是相对比较容易上手的VB进行开发。talk is cheap,先上程序:
' open_matlab.vb
Imports System
Module open_matlab
Sub Main()
Dim h As Object
Dim res As String
Dim matcmd As String
h = GetObject(, "Matlab.Application")
Console.WriteLine("MATLAB & Notepad++")
Console.WriteLine(" ")
while True
Console.Write(">> ")
matcmd = Console.ReadLine()
if matcmd.Equals("!!") then
Exit while
End if
res=h.Execute(matcmd)
Console.WriteLine(res)
End while
End Sub
End Module
具体语法先不谈(VB.NET语法在W3school有教程),说两个关键点:
那么总归效果如何呢?
我真的觉得海星
这种图窗安排有点像Pycharm的调试模式。上面写代码,下面可以随时执行,非常快乐了。
目前唯一的不足就是:如果输入ctrl+c中断信号,不能像MATLAB控制台一样中断当前命令继续执行,而是直接整个程序被kill了。这个目前还没有解决,可能会麻烦些,应该要深入理解Windows程序消息处理机制。相信VB是可以做到这一点的。这方面有懂的朋友欢迎评论区交流。
顺便附上编译VB用的NppExec脚本:
cd "C:\Users\xxxx\Documents\npp_selfpatch" // 我存NPP脚本的路径
vbc "$(FULL_CURRENT_PATH)"
INPUTBOX "Execute?y/[n]" : n // 提供一个编译后是否直接执行的选项,是个消息框
if $(INPUT)==y goto @exe // 众所周知DOS的分支很坑,所以用goto标签了
if $(INPUT)==Y goto @exe
if 1==1 goto @end
:@exe
"$(CURRENT_DIRECTORY)\$(NAME_PART).exe"
:@end
后记
这么一套操作细想下来还是很普适性的,所有脚本语言都能用类似的方式搞成这个样子(MATLAB还属于调教难度比较大的那种了,Python就更简单,直接运行解释器就完事了)
NppExec下面的也可以搞成shell、ssh等等,总之很有扩展性。
这个automationAPI是我在研究JupyterNotebook时偶然注意到的。我的下一个目标可能就是要在远端Jupyter上运行MATLAB(不过可能有点难)。不过我近期可以做的就是3b1b的那套动画包配置环境的心得,感觉也还是有话要说的。
我的专栏感觉快成了配置环境的专场了啊(苦笑)
另外封面图意外的是MATLAB logo骑在NPP logo上面,暗示了什么?