无处不在的.NET:在Matlab中使用WPF
最近园子里在讨论.NET程序员努力提高自身素质的问题。园子是.NET爱好者的大本营,大家都对这门技术充满了热情。然而不能不说的是,在国内说到.NET,80%以上的语境恐怕是指ASP.NET,这无形中助长了非.NET程序员,尤其是C++程序员和C++出身的技术主管对.NET的偏见和藐视,因为C++的领域大多看上去比做网站“更有技术性”。
国内某C++出身的主管认为同样的逻辑用C++实现就会“更加底层”,用.NET就会被微软牵着鼻子走。不禁要问用C++难道能脱离调用Win32 API不成。他反复强调C++的可移植性,认为Mono远远不够成熟。他竟以为他们基于VC开发的东西只要稍作修改就可以运行于iPhone之上。
事实上.NET无论是用于科学研究还是用于生产,肯定都比C++有优势。今天我们要看的例子与科学研究有关。在21世纪的第一个10年过去后,国内院校和科研院所仍然流行着VB6。然而在国外,JVM和CLR平台,甚至是html5,早就是教授和学生们的利器了。很多老外的软件中都集成了面向科学研究人员而非专业开发者的.NET扩展功能。本人在做本科毕业论文时就用到了3ds max中MaxScript脚本调用.NET,用这一特性制作了Windows Forms界面来操控3ds max场景。
说到.NET平台的脚本(或者说解释型语言),大家都会想到IronPython、IronRuby之类;说到交互式命令行,再加上F#等,将来可能C#也会提供交互式的功能。这里我要说其他软件中的这些功能其实一点也不差。在Mathematica和Matlab数学软件中,均提供了对JVM和.NET的接口。借助这两个类库的强大功能,科研人员能做的事情一下子多了起来。
以Matlab为例,你可以在交互式命令行和脚本中同时使用JDK和BCL两个牛库,这等于实现了一定程度上的JVM和CLR的互通。最近对这方面兴趣大增,正在研究更多的内容。
今天我举一个Matlab中使用WPF的例子。在这个例子中,演示了Matlab中.NET对象的基本使用方法、使用Matlab函数句柄作为匿名函数作为事件处理器的方法等。希望对想给你的Matlab程序增加界面的童鞋有所帮助。
以下代码在Matlab R2010b中测试通过。
% load necessary assemblies for
WPF
NET.addAssembly('PresentationCore');
NET.addAssembly('PresentationFramework');
NET.addAssembly('WindowsBase');
% show a window with a clickable
button
window = System.Windows.Window;
window.Title = 'WPF in MATLAB';
window.Width = 300;
window.Height = 100;
window.WindowStartupLocation =
System.Windows.WindowStartupLocation.CenterScreen; % use of enum
button =
System.Windows.Controls.Button;
button.Content = 'Click me!';
addlistener(button, 'Click', @(sender,
e)System.Windows.MessageBox.Show('Button clicked!')); % use of event handler
window.Content = button;
window.Show()
别的地方都很简单,我只解释一下“函数句柄”。这是Matlab最近几年加入的功能,很多国内教科书上都没有介绍,我也是在Matlab文档中偶然看到的,可见文档是最好的教材。函数句柄相当于C#中的匿名函数或lambda表达式这样的概念,有了它,Matlab中很多函数的使用更方便了。例如求定积分quad,以前需要把被积函数做成独立文件,然后把函数名用字符串形式传入。后来有了inline函数,但也不方便。再后来就有了函数句柄,于是我们可以直接写
quad(@sin, 0, 1)
quad(@(x)sin(x)+1, 0, 1)
等等。其中第二个就是一种lambda表达式的形式,@(x)sin(x)+1翻译成C#的lambda表达式就是x=>Math.Sin(x)+1。
针对函数句柄,Matlab现在有一些全新的函数。例如绘制函数图像,再也不需要先求两个向量了,直接可以使用fplot和ezplot。
在addlistener函数中,第一个参数是控件,第二个参数是事件名,第三个参数就是事件处理函数,以函数句柄形式传入。可以写一个独立的函数,也可以使用匿名函数(像代码中那样,@(sender, e)MessageBox.Show(…))。
大家不妨尝试一下:用WPF做界面,来调用java.math.BitInteger类计算大整数的幂。以下是命令行交互的结果:
>> a=java.math.BigInteger(2)
a =
2
>> a.pow(100)
ans =
1267650600228229401496703205376