使用MATLAB引擎库函数实现.NET下调用MATLAB
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3.2 什么是应用程序编程接口(API)
API 是一套用来控制 Windows 的各个部件(从桌面的外观到为一个新进程分 配的内存)的外观和行为的一套预先定义的 Windows 函数。用户的每个动作都会 引发一个或几个函数的运行以告诉 Windows 发生了什么。 这在某种程度上很象 Windows 的天然代码。 其他的语言只是提供一种能自动 而且更容易的访问 API 的方法。
1 引言
MATLAB 是一款具有极其强大的矩阵计算以及仿真能力的科学及工程计算软 件。其代码非常简单、易懂、易学,这大大缩短了软件的开发周期。而其提供的 工具箱,更是使其在各领域(包括信号处理(Signal Processing) 、图像处理 (Image Processing) 、小 波 分 析( Wavelet)等大量现代工程技术学科的内容[1]) 有着极其广泛的应用。到目前的 MATLAB2008 版本,其提供的工具箱已经达到了 40 多个。 .NET 则是现在进行软件开发的主流平台。 如果能在.NET 中使用 MATLAB 的工 具箱,就可以在未来的开发项目中赢得更高的生产力。 但遗憾的是,尽管 MATLAB 提供了各种工具使用户能够能方便地在其他语言 中使用 MATLAB,但是效果并不是很理想。二者之间的支持仍然不尽人意。 在这种情况下,我考虑用 MATLAB 的引擎库函数,来实现.NET 下对 MATLAB 的调用。 在这里使用的是.NET 平台下的 C#.NET 语言进行开发。 开发环境: Windows XP SP2;Microsoft Visual Studio 2008;MATLAB 2006b。
3.4 数据封送技术
3.4.1 自定义封送处理概述 封送拆收器实质上是提供了新旧接口功能之间的互用渠道。 自定义封送拆收 器使您设计的客户端既能够与旧接口协同工作, 也能与仅实现新接口的服务器协 同工作。自定义封送拆收器还使所生成的客户端既能够与新接口协同工作,也能 与公开旧接口的服务器协同工作。 除了使用互用封送拆收器之外,还可以为接口设计自定义封送拆收器,以引 入不同的封送处理行为或以不同的方式向 COM 公开接口。通过使用自定义封送 拆收器,您可以尽量减小新 .NET 组件和现有 COM 组件之间的差异。 例如,假设您在开发一个名为 INew 的托管接口。当通过标准的 COM 可调
(Server Name)及话题(Topic) 。服务名通常是应用程序的可执行文件名。话 题分为两类:System 及 Engine,每个话题为更详细的子话题。 由于 DDE 进行数据交换是基于 Windows 剪贴板的, 所以在进行一些复杂数据 , 如矩阵数据交换时,性能表现不佳
[2,3,4]
。
3 基于 MATLAB 引擎库的对象化包装
3.1 MATLAB 的引擎库函数
MATLAB 以动态链接库方式提供引擎函数的定义(libeng.dll、libmat.dll、 libmx.dll) 。同时,在 MATLAB 路径下\R2006b\extern\include 中的 engine.h、
mat.h、matrix.h 中声明各引擎库函数。 常用的 MATLAB 引擎库函数及其功能如表 1 所示[5]。
.NET 中创建代码如下: MATLAB = CreateObject(“MATLAB.Application”) 在这种情况下,MATLAB 自动化服务器与应用程序中的数据传递通过 COM 数 据接口进行[2]。 这种方式是 MATLAB 公司推荐使用的方式,它使用起来非常简单。但是,由 于.NET 与 MATLAB 的参数变量并不完全相同,这需要在调用组件的方法时将.NET 的变量类型转化为 MATLAB 中对应的变量类型。这就使得它效率比较低。此外, COM 方式还存在一个缺陷,在使用 MATLAB 进行图形绘制时,有可能得到不准确 的结果,尤其是在绘制三维图形方面。
如果在 C 语言中使用 MATLAB 引擎, 只需要引用上述的三个头文件 (.h 文件 ) 即可。但在.NET 中使用起来就非常困难,首先由于.NET 是完全面向对象的程序 设计,不容许独立存在的外部函数,所有的函数都必须以方法的形式存在某一个 类中;其次由于.NET 托管代码中的数据类型与 MATLAB 引擎库函数的数据类型不 兼容,这就造成托管代码与引擎库函数之间数据交换的困难。 此外,.NET 只能访问托管代码中支持的数据类型,例如 system.Int64,虽 然微软公司在设计.NET 时已经实现了非常丰富的数据类型,这些数据类型比 C 及 C++多得多,但由于在两种语言中对数据类型表示的不一致,造成了.NET 不能 识别引擎库函数中基于 C 语言和 Windows API 的数据类型。 这里,使用.NET 的平台调用技术和数据封送技术就可以很好地解决。
2.2 COM 方式
COM(Component Object Modle,组件对象模型)是组建之间相互接口的规 范,是 OLE(Object Linking &Embedding)和 ActiveX 共同的基础,其作用是 使各种软件构建和应用软件能够用一种统一的标准方式进行交互。 COM 本质上仍然是客户/服务器模式。客户(通常是应用程序)请求创建 COM 对象并通过 COM 对象的接口操纵 COM 对象。服务器根据客户的请求创建并管理 COM 对象,客户和服务器这两种角色并不是绝对的。 MATLAB 支持组件自动化(COM Automation) ,即允许一个程序或组件去控制 另一个程序或组件,MATLAB 支持的组件技术主要包括以下几个方面: 在 MATLAB 下运行其它软件的组件。 在其他程序下运行 MATLAB 的组件(包括 MATLAB 自 身 ) 。 将所需的 MATLAB 功能(通常由若干个 M 和 MEX 文件构成)用 MATLAB 自带工 具 COM Builder 自动转换生成组件,以供其它程序使用。 要在控制程序中开启自动化服务器,需要指导 MATLAB COM 对象在系统注册 表中定义的名字,即 Prog ID。通常 Prog ID 取以Байду номын сангаас两个名字中的一个: MATLAB Application,将 MATLAB 自动化服务器作为共享服务器。 MATLAB Application.Single, 应用程序独享 MATLAB 自动化服务器。
用包装向 COM 公开时,该接口具有与托管接口相同的方法,并且采用内置于互 用封送拆收器中的封送处理规则。进一步假设有一个名为 IOld 的已知 COM 接 口已经提供了与 INew 接口相同的功能。通过引入自定义封送拆收器,可以提供 IOld 的非托管实现,它只需将调用委托给 INew 接口的托管实现。自定义封送 拆收器实质上充当了托管和非托管接口之间的互用渠道(注意:在仅调度接口上 从托管端向非托管端进行调用时,并不调用自定义封送拆收器) 。 3.4.2 定义封送处理类型 在生成封送拆收器之前,必须定义所封送的托管和非托管接口。这些接口通 常执行相同的功能,但以不同的方式向托管和非托管对象公开。 托管编译器将从元数据中生成托管接口, 所得的接口看起来与其他任何托管 接口都相似。 用户用接口定义语言 (IDL) 定义非托管类型,然后用 MIDL 编译器对其进 行编译。应在库语句中定义该接口,然后用通用唯一标识符 (UUID) 属性为其分 配一个接口 ID。 3.4.3 用平台调用封送数据 若要调用从非托管库导出的函数,.NET Framework 应用程序需要在托管代 码中包含表示该非托管函数的函数原型。 若要创建使平台调用能够正确封送数据 的原型,您必须执行以下操作: 将 DllImportAttribute 属性应用于托管代码中的静态函数或方法。 用托管数据类型替换非托管数据类型。 可以使用随非托管函数提供的文档来构造等效的托管原型,方法是通过它 的可选字段来应用属性并用托管数据类型替换非托管类型
2 现在使用比较广泛的 MATLAB 与.NET 接口实现方法与优缺点
2.1 DDE 方式
DDE(Dynamic Data Exchange)是 Windows 系统下允许应用程序间交换数据 的一种通信机制。MATLAB 作为 Windows 下的一个应用程序,可以借助 DDE 与其 它应用程序通信。 当客户程序创建 DDE 对话时,需要知道服务器程序的两个参数:服务名
API 函数 MessageBeep 按以下方式: BOOL MessageBeep( UINT uType ) 编写时,外部方法就必须使用 CLR 类型来定义, 如您在前面的代码片段中所 看到 的 。 需 要 使 用 与 基 础 API 函数 类 型 不 同 但 与 之 兼 容 的 CLR 类型 是 P/Invoke 较难使用的一个方面。 3.3.1 C#代码直接调用非托管代码的方法 C# 代码 有以下两种可以直接调用非托管代码的方法: 1) 直接从 C# 调用 DLL 导出。 2) 调用 COM 对象上的接口方法。 对于这两种技术,都必须向 C# 编译器提供非托管函数的声明,并且还可能 需要向 C# 编译器提供如何封送与非托管代码之间传递的参数和返回值的说明。 3.3.2 调用格式实例 using System.Runtime.InteropServices; //引用此名称空间,简化后面的代码 //使用 DllImportAttribute 特性来引入 API 函数,注意声明的是空方法, 即方法体为空。 [DllImport("user32.dll")] public static extern ReturnType FunctionName(type arg1,type arg2,...);//调用时与调用其他方法并无区别 3.3.3 参数类型 数值型直接用对应的就可(DWORD -> int , WORD -> Int16) ; API 中字符串指针类型 -> .net 中 string; API 中句柄 (dWord) -> .net 中 IntPtr; API 中结构 -> .net 中结构或者类。 注意这种情况下, 要先用 StructLayout 特性限定声明结构或类。
3.3 平台调用技术
.NET 公共语言运行库(CLR)的 interop 功能,也称为平台调用(P/Invoke)。 它允许托管代码调用在 DLL 中实现的非托管函数。 C# 的 规 则 之 一 是 它 的 调 用 语 法 只 能 访 问 CLR 数 据 类 型 , 例 如 System.UInt3。C# 显然不识别 Windows API 中使用的基于 C 的数据类型(例 如 UINT 和 BOOL) , 这 些 类 型 只 是 C 语言类型的类型定义而已。 所以当 Windows
表 1 C 语言计算引擎控制函数
MATLAB 引擎库函数 engOpen engClose engGetVariable engPutVariable engEvalString engOutputBuffer engOpenSingleUse engGetVisible engSetVisible
关键词:MATLAB .NET 接口
ABSTRACT : We can resolve many problems effectually in using MATLAB toolbox. But it’s bad in supporting .NET. And .NET is the main platporm today. So, it’s necessary to research the interface between them. This paper realizes it by using MATLAB Engine. Key words:MATLAB ; .NET ; Interface
使用 MATLAB 引擎库函数实现.NET 下调用 MATLAB
陈正伟(xczwx@)
摘要:利用 MATLAB 提供的工具箱可以有效地解决各种科学及工程问题。但其 对.NET 的支持非常差,而.NET 又是各种应用的主流平台,因此有必要研究二者 的接口。本文使用 MATLAB 的引擎库函数实现在 C#.NET 下调用 MATLAB。
功能描述 启动 MATLAB 引擎 关闭 MATLAB 引擎 从 MATLAB 引擎获取 MATLAB 数组 向 MATALB 引擎发送 MATLAB 数组 执行 MATLAB 命令 创建缓冲以存储 MATLAB 文本输出 启动一个专用的 MATLAB 引擎 获取 MATLAB 引擎是否可见 设置 MATLAB 引擎是否可见