Delphi与Matlab混合编程的设计与实现 联系客服

发布时间 : 星期六 文章Delphi与Matlab混合编程的设计与实现更新完毕开始阅读e9917d222f60ddccda38a0c4

Delphi与Matlab混合编程的设计与实现 张宏伟,许晓兵,吕文元

(上海大学大学 管理学院,上海 200093)

摘要:本文介绍了Delphi和Matlab进行混合编程的四种方案。重点介绍了Matlab作为自动化服务器和COM组件两种编程方案的步骤和实例。

一、引言

Matlab是MathWorks公司开发的高性能的科学与工程计算软件。它在数值计算、自动控制、信号处理、神经网络等领域有着广泛的应用。Matlab被称为“草稿式”语言,简单易学,编程效率高、可扩充性强。然而Matlab运行效率低、源代码保密性差等缺点限制了它作为通用软件开发平台。Delphi是Borland公司开发的通用开发工具。“真正的程序员用C,聪明的程序员用Delphi”,这是对Delphi的最经典评价。Delphi是面向对象的开发工具,编译效率高、功能强大。

Matlab的强大主要体现在它的开放性和可扩展性,以及众多面向不同领域的工具箱。Matlab提供一些接口简化Matlab与其他开发工具的交互。Delphi与Matlab进行混合编程可以有效地发挥Matlab的数值分析的强项和Delphi编程简洁高效的特点。 二、Delphi调用Matlab的方案

Delphi调用Matlab主要有以下几种方案:

①Matlab自动化服务器。自动化服务器的核心是包含基于Idispatch的接口。Matlab作为自动化服务器,可以被Windows平台上任何可以作为自动化控制器的应用程序使用,调用需要Matlab环境。

②Matlab引擎。Matlab本身没有提供和Delphi之间的接口程序,但是可以利用Matlab 和VC 之间的接口函数,在 VC 下利用Matlab 引擎做成DLL供Delphi调用。Matlab引擎与后台Matlab服务器建立连接,实现命令和数据信息的传递。这种方式需要Matlab在后台运行,离不开Matlab环境。这不利于软件的开发,但是它可以充分利用Matlab的功能,包括调用工具箱函数和图形函数。

③调用Mideva生成的动态链接库。Mideva是MathTools推出的Matlab编译开发平台,提供对Matlab程序的解释执行和开发环境支持。其最主要特点是能够将M文件转化为C语言代码,并通过C++将其编译成可执行程序或DLL。用Mideva生成的DLL一般不能直接使用,需要用VC对其进行封装成DLL供Delphi调用。这种实现脱离Matlab运行环境,便于软件的发布和移植。

④调用COM接口编程。利用Matlab的COM Builder工具可以将所需的Matlab功能自动转化为一个COM组件,供其它应用程序调用,这种方式可以脱离Matlab环境运行。

第二种和第三种方案实现相似,都需要把对Matlab的调用用VC封装成动态链接库,然后Delphi调用动态链接库实现混合编程,在[2]中对这两种方案作了详细的介绍。本文主要介绍第一和第四种方案

三 方案实现举例 1. 自动化服务方案

自动化服务器是可以供其它应用程序驱动的组件。通过Matlab的自动化服务器,其他的应用程序可以执行Matlab命令,并可以向Matlab工作空间传递和获取操作数据。客户程序获取和控制Matlab服务器步骤如下:

(1)初始化自动化服务器。Matlab提供自动化对象的名称是MATLAB.Application。获取Matlab对象,在Delphi中语句实现为:

mHandle = CreateOleObject(MATLAB.Application) (2)操作Matlab自动化对象。自动化函数对象主要有: Execute:调用Matlab命令;

MinimizeCommmandWindow,maximizeCommandWindow:最小化,最大化自动化服务器; GetCharArray,GetFullMatrix,GetWorkspaceData:获取自动化服务器空间数组数据;

PutCharArray,PutFullMatrix,PutWorkspaceData:设置自动化服务器空间数组数据; (3)释放Matlab自动化对象。在Delphi中调用语句为: mHandle.Quit

2. 自动化服务器实现举例

下面以一个简单的画图程序为例介绍Matlab的调用。

(1)在Matlab环境下编写一个M文件,文件名为drawexample.m,其源代码为: function [out] = drawexample(n)

rdata=[2 5 64 75 89 97 111 130 155 166 241 260]; histfit(rdata,n); out=n;

把drawexample.m放置在Matlab的搜索路径下,否则程序不能执行出正确结果。 (2)Delphi中建立调用自动化功能项目。

首先,启动Delphi,在“File”菜单中选择“New Application”,生成一个应用程序。在界面上放置一个按钮。 其次,在Uses单元中加入comobj单元,在界面上双击按钮,编辑该按钮的事件,修改其代码如下: procedure TForm1.btn1Click(Sender: TObject); var

oReal: OleVariant; oImage: OleVariant; Result: string; num: Integer; mHandle: OleVariant; begin

mHandle := CreateoleObject('Matlab.Application');//创建自动化服务器对象 mHandle.MinimizeCommandWindow;//最小化服务器对象 num := 5;//设置调用参数

oReal := VarArrayCreate([1, 1], varDouble); oImage := VarArrayCreate([1, 1], varDouble); oReal[1] := num;

mHandle.PutFullmatrix('n', 'base', VarArrayRef(oReal), VararrayRef(oImage)); mHandle.Execute('c=drawexample(n)'); Result := mHandle.Execute('c');

ShowMessage(Result);//显示调用返回的结果 mHandle.Quit; //关闭自动化对象 end;

编译并执行可以看到运行结果如图1所示: 图一 Delphi调用Matlab自动化服务器例子 3. COM接口方案

COM为组件和应用程序通讯提供了统一的标准,是一种通用的对象接口,任何语言只要按照这种接口标准,就可以实现相互调用,可以把组建看成“搭建”软件的积木块。Delphi调用Matlab提供的COM组件步骤如下:

(1)建立COM对象,通过Delphi自带的COM Builder工具可以方便地生成COM对象。 (2)在Dephi中引用COM对象。 (3)编写代码实现对COM对象的调用。

为了保证能被其他编译器调用,需要做一个准备工作,打开一个dos窗口,进入$Matlab$/bin/win32($Matlab$为Matlab的安装目录)输入regsvr32 mwcomutil.dll,即对mwcomutil.dll进行注册(Matlab的任何COM组件都要用到这个DLL)。

4. COM接口方案举例

仍以drawexample.m为例,生成COM组件。 (1)创建COM组件

在Matlab命令行中输入comtool,打开Matlab Builder。在“File”菜单中选择“New Project”,在“Component name”里填上“drawcom”,点击“OK”按钮。

点击“Add File”按钮,选择drawexample.m文件加入工程。 点击“Build”菜单的“COM Object”。

默认情况下在Matlab的工作目录下生成一个drawcom的文件夹,编译成功后,就会在drawcom\\distrib\\文件夹下生成有comtest_1_0.dll文件,它就是生成的COM组件,编译时Matlab已经对此DLL进行了注册。

(2)Delphi调用COM组件

首先,启动Delphi,在“File”菜单中选择“New Application”,生成一个应用程序。在界面上放置一个按钮。 其次,在“Project”菜单中选择“Import Type Library…”。在“Import Type Library”界面选择刚生成comtest_1_0.dll文件,点击“Install…”按钮。

在组件面板中找到ActiveX选项卡,把组件drawcomclass放到界面上。命名为drawcom1,在界面上双击按钮,编辑该按钮的事件,修改其代码如下: procedure TForm1.btn1Click(Sender: TObject); var

c , n : OleVariant; begin

n :=4.0;//注意不能写成4 drawcom1.drawexample(1,c,n); end;

实现的效果和图一相同。 四、结束语

本文讨论了Delphi与Matlab的混合编程,主要集中讨论在Delphi中调用Matlab的自动化服务器和COM两种方法,并给出了2个例子。可以看出,通过混合编程,可以把两者的优势充分地结合起来,既有效地利用了Delphi 强大的可视化编程的功能,同时也充分利用了Matlab强大的运算能力,使得编程者不必重新编写复杂的算法,从而极大程度地提高了编程的效率。

参考文献

[1] 瀚海星云 论坛[EB/OL]. http://bbs.ustc.edu.cn/main.html,2006-07-15. [2] 杨高波,亓波. 精通MATLAB 7.0混合编程[M].北京:电子工业出版社.2006.

Visual C++2005生成可用的matlab DLL的步骤

为了在delphi 7.0中使用matlab函数,决定做一个DLL,原理是利用matlab提供的引擎,在delphi中调用DLL后,DLL激活matlab引擎,把delphi中输入的matlab指令提供给matlab执行,执行完毕后,再将数据通过DLL传回Delphi。 所以第一步要整一个delphi可用的dll出来,这里选择用VC2005来做这个dll。步骤如下: 一、在VC2005中新建一个DLL项目。(VC是中文版,matlab是r2007a版本) 二、编译器环境设置:

1、项目->属性->配置属性对话框->C/C++->常规->在“附加包含目录”中填入: F:\\Program Files\\MATLAB\\R2007a\\extern\\include

目的是为了让VC能认识matlab引擎以及一些matlab特有的函数。 2、项目->属性->配置属性对话框->链接器->常规->在“附加库目录”中填入: F:\\Program Files\\MATLAB\\R2007a\\extern\\lib\\win32\\microsoft 3、项目->属性->配置属性对话框->链接器->常规->在“附加依赖项”中填入: Libeng.lib libmx.lib libmex.lib libmat.lib 三、新建CPP文件,命名为DelphiMatlab: 我写的程序如下:

// DelphiMatlab.cpp : 定义 DLL 应用程序的入口点。 #include #include #include

#include \申明要用到matlab引擎 #ifdef _MANAGED

#pragma managed(push, off) #endif

BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) {

return TRUE; }

#ifdef _MANAGED #pragma managed(pop) #endif

engine *ep=NULL; //Matlab引擎,全局变量

mxArray *PA=NULL; //Matlab数组指针。可根据需要定义多个mxArray指针变量