|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?我要加入
x
概述:本文阐述了如何利用Delphi灵活强大方便的编程能力和Matlab强大的科学计算能力,降低编写复杂算法的难度和时间,使Delphi算法程序的开发效率大大提高,收到事半功倍的效果。
关键字:Matlab、科学计算、接口、数据交换
引 言:
最近在搞一个数字图像加密的课题,其中涉及到大量的矩阵及其他科学运算,在用Delphi实现时,可以想象在编写算法的时候遇到了大量的问题,所以提出了这样一个想法:能否将后台运算模块通过某种接口的方式交由其他成熟的科学计算软件处理,而用Delphi从事其前台开发,这样将大大降低编写复杂算法的难度和缩短开发周期。相信这也是广大开发人员在遇到大量科学计算时所急待的问题,在论坛上也屡有人问起,笔者参阅了大量资料后归纳整理了几种方案,希望对大家有益^_^
Delphi与MATLAB数据接口方案探讨
前言:
Delphi作为一种功能强大的编程工具,具有易学易用、开发效率高,界面制作美观方便等优点,因此被很多程序员所青睐。Pascal作为历史上第一种结构化的高级语言,在从事复杂算法编写方面也有着诸多优点,可是在软件开发快速运作的今天,用Pascal原始开发一些复杂的算法,不仅编译效率不高而且也影响开发进度,因此Delphi如何与科学计算软件相结合,从而高效地完成编程任务成为一个困扰很多程序员的问题。而Matlab就正是一种高效率的科学工程计算语言,它在矩阵运算、数值计算、数字信号处理、系统识别、自动控制、神经网络、图形显示等方面比其它语言有难以比拟的优势。将Delphi和Matlab相结合,利用Delphi灵活强大方便的编程能力,Matlab强大的科学计算能力就可以开发出功能强大、操作灵活的软件。
以下给出5类数据接口方案供大家参考:
(为了便于大家浏览,几种方案将分贴显示)
方案一 采用数据中转方式实现Delphi与Matlab交流.....................................2楼
方案二 基于DDE技术的动态数据交换..................................................3楼
方案三 创造ActiveX对象实现数据交流................................................4楼
方案四 利用动态链接库技术实现二者交流.............................................5楼
方案五 利用mideva编译脱离matlab环境的动态链接库(注:此方法笔者尚未成功).........6楼
2003-8-18 21:21:00
查看评语»»»
2003-8-18 21:22:54 方案一 采用数据中转方式实现Delphi与Matlab交流
一、基本思路
Matlab输入数据的方法很多,其中利用M文件,直接把数据按元素列表方式引入Matlab工作内存方法,不仅语法简单,而且运行时只要输入文件名,Matlab就会自动按顺序执行M文件中的语句;Matlab数据输出的方法也有很多种,为了便于与Delphi应用程序接口,我们可以利用Matlab的指令Save输出数据。如指令Save outfile.dat x y -ascii -double,可将变量x和y以16位ASCII码形式存入outfile.dat文件。
基于上述matlab数据输入,输出的方法,我们可以利用M文件为中转,实现Delphi和Matlab的数据交换,当是要注意以下几点:
(1)由于Matlab的基本数据单位是矩阵,所以在delphi应用程序中我们只有通过文件变量,将参与运算的数据输出成M文本文件,以创建和保存矩阵数据。
(2)由于Delphi应用程序在前台运行,因此在应用程序中调用Windows函数WinExec,即可执行Matlab.exe。
(3)由于M文件,只有在Matlab集成环境中才能被识别和自动执行,而根据后台的要求不能显示地进入Matlab集成环境,考虑到Matlab环境变量由matlabrc.m文件定义,因此我们可以通过对matlabrc.m文件的修改(将Matlab要完成的输入数据、进行计算、输出数据过程、编写成M文件,加入matlabrc.m中),从而实现Matlab的后台运作。
二、Delphi如何将数据传递给Matlab
这里举例说明更直观一些^_^
例:进行矩阵运算(b''*b) -1 *b''*y'', 其中b是t*2矩阵,y是1*t矩阵。
在Delphi应用程序中,可以采用以下的程序段将参与运算的矩阵b、y保存成M文件,这样Matlab就可以通过执行相应的M文件,获得参与运算的矩阵b、y。应用程序段如下:(程序段中fb、fy是事先定义好的textfile类型的文件变量,b[i,j]、y是事先定义好的数组变量;''c:\matlabfile\delphioutb.m''是保存矩阵b的M文件路径及文件名,''c:\matlabfile\delphiouty.m''是保存矩阵y的M文件路径及文件名)
*********创建保存矩阵b的M文件*********
//注:在Matlab中整个输人矩阵必须以"[]"为其首尾,矩阵的行与行之间必须用分号";"或回车位隔离,矩阵元素必须由逗号","或空格分离。
assign(fb,''c:\matlabfile\delphioutb.m'');
Rewrite(Fb);
write(fb,''b['');
for i:=0 to t-2 do
for j:=0 to 1 do
begin
Write(Fb,b[imk]);
if j<1 then Write(Fb,'','')
else if (i<t-2) and (i=1) then write(Fb,'';'')
else write(fb,'']'');
end;
CloseFile(Fb)
*********创建保存矩阵y的M文件*********
assign(fy,''c:\matlabfile\delphiouty.m'');
Rewrite(Fy);
write(fy,''y=['');
for i:=1 to t-1 do
if i<t-1 then write(Fy,y,'','')
else write(fy,y,'']'');
CloseFile(Fy);
三、Matlab如何接受应用程序传递来的数据并进行计算
前面介绍过,由于M文件只有在Matlab集成环境中才能被识别和自动执行,而根据后台运作的要求不能显示地进人Matlab集成环境。但我们可以通过对matlabrc.m文件的修改,将Matlab要完成的操作编写成M文件,加人matlabrc.m中。下面笔者仍依前面例题的计算要求,来说明如何编写Matlab接收数据、进行计算、数据输出的M文件(取名为c:\matlabfile\Mymatlabfile.m).
1、用记事本输入以下代码,保存在自己的目录(如c:\matlabfile)下,取名为Mymatlabfile.m。
delphioutb //保存矩阵b的M文件
delphiouty //保存矩阵y的M文件
m=((b'')*b'')*(y'')
save c:\matlabfile\matlaboutfile.dat m -ascii -double
quit
2、打开matlabrc.m将其保存为一个备份文件matlabrcbak.m,然后对原文件进行编辑,将下列语句加在文件最后:
if exist(''c:\matlabfile\Mymatlabfile.m'')
Mymatlabfile
end
3、完成上述内容后,只要在应用程序中启动MATLAB,就会完成相应操作。
四、在Delphi中如何启动Matlab
将前面步骤处理完后,我们可以用以下程序隐式启动Matlab。
copyfile(''c:\dsm\matlabfile\Mymatlabrc.m'',''c:\matlab\toolbox\local\matlabrc.m'',false);
winexec(''c:\matlab\bin\matlab.exe'',SW_MINIMIZE);
五、Delphi如何接受Matlab输出结果
Matlab将计算结果通过save c:\matlabfile\matlaboutfile.dat m -ascii -double进行输出,所以我们可以通过下面程序获取计算结果,并将结果通过double类型变量mid放进数组a中:(Fa为textfle类型变量)
if FileExists(''c:\matlabfile\matlaboutfile.dat'') then AssignFile(Fa,''c:\matlabfile\matlaboutfile.dat'');
Reset(Fa);
i:=0;
While not Eof(Fa) do
begin
read(Fa,mid);
a:=mid;
i:=i+1;
end;
closefile(Fa);
另外,在应用上述步骤完成接口后,还需要在应用程序中添加以下代码,以还原Matlab原始环境参数设定:
copyfile(''c:\matlabfile\matlabrcbak.m'',''c:\matlab\toolbox\local\matlabrc.m'',false);
六、方案总结
此方案利用文件形式进两个应用程序之间的数据传递,方法比较直观,在运行调试的时候可以较方便地传递数据的内容。但是,由于采用数据中转的方式,所以在有大量数据频繁传递的时候,运行速度受到很大影响。
2003-8-18 21:23:57 方案二 基于DDE技术的动态数据交换
一、基本思路
方案一需要用文件形式来进行两者的数据传递,那么是否有两者直接数据传递的解决方案呢,答案是肯定的。我们知道DDE是基于Windows的一种消息机制,在客户机和服务器程序间通过互相传通消息进行“对话”,它允许两个或两个以上的应用程序之间进行实时的数据交换。根据这点,我们可以利用DDE来实现Delphi和matlab的数据传输。
二、DDE应用协议
DDE中提出对话的一方称为客户程序(client),而作出反应的一方称为服务器程序(server)。DDE服务器负责维护其他Windows程序所使用的数据,而 DDE客户机则负责从服务器获取数据。应用程序之间的动态数据交换必须遵守DDE协议,DDE协议主要有三层,应用程序层(Application)、对话主题层(Topic)和对话项目层(Item),各层的定义分别为:
1 应用程序层(Application)
应用程序层主要是建立对话的通道,DDE对话通常是由客户程序引起的,包括初始化有关参数、准备开始对话等。
2 对话主题层(Topic)
对话主题是DDE服务器所能识别的数据单元,通常是一个文件名、窗体名,在Delph 中还可以是Serverconv组件的名字、对于Matiab服务器,主题主要有两个:System和Engine,详见表一。
3 对话项目层(Item)
对话项目层是用来确定客户程序和服务器程序进行动态数据交换的内容,如发送数据、接受数据或者数据库中的字段、表格中的单元等.在Delphi中应用程序中,就是DdeServerItem组件的名字。在Matlab中两个主题System和Engine分别包含有Systems,Format,Topics,EngEvalstring,EngSringResult,EngFigureResult等项目,在表一中可以查看详细情况.
Madab和Delphi都支持DDE技术,既可以作为客户程序。又可以作为服务器程序、这里我们仅以Delph作为客户程序,Matlab作为服务器程序进行探讨,Delphi客户机通过DDE组件提供的函数与Matlab的DDE服务器模块进行对话,完成数据的动态交换.
三、Delphi 的DDE组件
表1 Matlab DDE服务器的组成
System主题
项目: 功能:
Systems 包含System 主题所支持的全部项目列表
Format 包含Matlab DDE 服务器所支持的全部数据格式名的字符串列表
Topics 包含Matlab DDE服务器所支持的全部主题名的列表
Engine主题
项目: 功能:
EngEvalString 发送命令到Matlab服务器中执行
EngStringResult 从Matlab服务器中请求获取文本格式的数据
EngFigureResult 从Matlab服务器中请求获取图形格式的数据
<matrix> 从Matlab服务器中请求获取矩阵数据
Delphi提供了四个用于DDE的组件:Ddeclicntconv,Ddeclienlitem,Ddeserverconv和Ddeserverconv,其中前两个是用作客户程序,后两个是用作服务器程序.在将Delphi作为客户程序时,必须用到Ddeclientconv和Ddeclientitem组件、Ddeclientconv用于客户端同服务器建立对话和确立对话主题.重要的属性和方法有ConnectMode,Ddeservice,Ddetopic,Setlink,Pokedata.ExecuteMacro 等:Ddeclientitem用于客户端注册对话项目常用的属性和方法有Ddeconv,Ddeltem,Lines,对话时与服务器程序密切相关,向服务器端发送的数据和从服务器端返回的数据往往都在于此组件的lines属性中。它们的具体用法和定义可以从Delphi帮助文件中查到。
四、Matlab DDE服务器
在将Matlab作为服务器访问时,必须提供服务器的名字、主题和项目.在Win32系统中,Matlab的DDE服务器名为Matlab,支持两个对话主题:System和Engine,每个主题下面有几个项目,通过它们可以完成不同的任务.从表一中可以查着其对应的功能.
Madab作为服务器时,支持三种数据传输格式:文本格式、元文件图、XLTallle、其中文本格式用于存放空字符结尾的字符率数据格式.元文件图用于存放图形数据的格式,XLTable是为支持Excel所使用的一种特殊的数据格式.
五、Delphi和Matlab的DDE实现过程
DDE技术已经是非常成熟的windows进程间通信机制,Delphi和Matlab之间动态数据交换中我们将Delphi作为客户机,Matlab用作服务器。首先启动Delphi客户机,确立对话主题,然后连接Matlab服务器并建立DDE对话.在Delphi中,同服务器建立连接有自动和手动两种方式,可以通过declientconv组件的ConnectMode属性进行设置。前者必须调用Ddeclientconv组件的Openlink方法建立DDE对话,后者在连接时可以自动建立对话.确立对话主题并建立对话后 就可以根据不同的项目内容,在Delphi和Matlab之间实现不同数据的动态交换了,如向Matlab服务器发送命令和数据,向服务器请求返回数据,包括图形数据和文本数据等。
六、方案总结
直接在Matlab与Delphi间实现数据传输,提高了运行速度,但是步骤较为烦杂,有时候会莫名其妙的出错-_-b
2003-8-18 21:24:29 方案三 创造ActiveX对象实现数据交流
一、基本思路
ActiveX是由Microsoft制定的一种独立于编程语言的组件集成协议,它不受开发环境的限制。ActiveX控件能够在不同的环境中使用,包括Delphi,C++Builder,VC++,VB和Internet Explore等。Matlab和Delphi都支持ActiveX技术,因此,可以利用ActiveX自动化服务器和自动化控制器技术,实现Matlab 和 Delphi接口。
二、Matlab 自动化服务器
自动化服务器是一种可以由其他应用程序编程驱动的组件,其核心是要包含一个或多个供其他程序创建和连接的基于IDispatch的接口。Matlab作为自动化服务器时,可以被Windows平台上任何作为自动化控制器的应用程序使用。Matlab ActiveX对象在系统注册表中定义的名字(ProgID)为Matlab.Application.5 或者Matlab.Application.Single。用Matlab.Application.5作为ProgID创建Matlab自动化服务器时,系统将不再另外初始化其他服务器,而是作为共享服务器完成所有的论求。使用Matlab.Application.Single时,Matlab自动化服务器将作为一个单独的服务器使用,而不与其他程序共享。对Matlab自动化服务器的使用,系统提供了五个函救:Excute,PutFullMatrix,GetFullMatrix,MinimizeCommandWindow,MaximizeCommandWindow。其中,
Excute用于执行Matlab命令,PutFullMatrix和GetFullMatrix用于数据传递,MinimizeCommandWind和MaximizeCommandWindow用于界面窗口煤作。
三、Delphi自动化控制器
Delphi5提供两个函数用于ActiveX接口和对象编程:GetActiveOleObject和CreateOleObject,其格式为:
function GetActiveOleObject(const ClassName:string):IDispatch;
function CreateOleObject(const ClassName:string):IDispatch;
其中GetActiveOleObject用于访问当前运行的ActiveX对象表,返回指定的ActiveX对象;CreateOleObject用来创建指定的、宋初始化的ActiveX对象。可以通过调用这两个函数,创建一个Matlab 自动化服务器的对象实例。
四、实例程序
这里给出一个具体的例子来说明在Delphi中利用 ActiveX术实现Matlab的自动化。首先在unit的uses语句中加入uses ComObj。然后加入下列语句:
procedure TForm1.Button1Click(Sender:Tobject);
var matlab:variant;
begin
try
matlab:=GetActiveOleObject(''Matlab.Application'');
except
matlab:=CreateOleObject(''Matlab.Application'');
matlab:=CreateOleObject(''Matlab.Application.5'');
matlab.execute(''a=[1 2 3 4 5 6 7 8];'');
matlab.execute(''b=[2 3 4 4 5 6 2 2]'');
matlab.execute(''plot(a,b)'');
end
end;
五、方案总结
此方案采用win32程序下较为通用的ActiveX方式进行数据交换,实现起来简单明了。但是需要注意,每次程序运行的时候,在创建对象的时候会花费很长的一段时间,会生成一个matlab窗口(这个令人很不爽!)。笔者还遇到一个问题,不知道是不是特例,就是同样的图像数据在Matlab下运行后的结果和通过Delphi运行后的结果有时候有点不一样,比如我现在正在搞的图像加密,在两个环境加密后的图像质量就是不同(算法一样),莫名其妙…… |
|