第15章 应用程序接口

    MATLAB虽然是一个完整的科学计算与可视化的环境,但在很多情况下它仍需与其他外部程序沟通,可用MATLAB提供的应用程序接口(Application Program Interface,简称API)来实现此功能。

    MATLAB应用程序接口包括3部分内容,分别为MEX文件——外部程序调用接口,在MATLAB中调用C语言或者Fortran语言编写的程序,以提高数据处理的效率;MAT文件应用程序——数据输入输出接口,向MATLAB环境传送数据或从MATLAB环境接收数据,即实现MATLAB系统与外部环境的数据交换;MATLAB计算引擎函数库——在MATLAB和其他应用程序间建立客户机/服务器关系,将MATLAB作为一个计算引擎,在其他应用程序中调用,从而降低程序设计的工作量。MATLAB在Windows平台上支持Microsoft提出的COM标准,同时支持Java语言,所以MATLAB几乎可以同Windows平台上任何一种软件或者开发语言进行交互。

    本章将重点讨论这些应用程序接口的实现方法。

    15.1 创建C语言MEX文件

    本节将介绍在MATLAB中创建C语言的MEX文件的方法,在这之前,首先对MEX文件作一个简要的介绍。

    15.1.1 MEX文件简介

    MEX从字面上是MATLAB和Executable两个单词的缩写。一般MEX文件使用C语言或者Fortran语言进行开发,通过适当的编译后,生成的目标文件能够被M语言解释器调用执行,这种文件在Microsoft Windows下使用后缀.dll。MEX文件重要应用于已存在较大规模的C和Fortran程序,可以比较容易的在MATLAB中调用或是在MATLAB中运行不很有效,存在计算瓶颈或是直接面向硬件编写的C和Fortran程序可以通过MEX文件被MATLAB调用。

    “阵列”是MATLAB惟一能处理的对象,在C语言中,MATLAB“阵列”用结构体mxArray定义。

    下面通过一个最简单的MEX文件示例来认识MEX源文件的结构。

    【例15.1 】简单MEX文件示例——mexhello.c

    示例代码设置如下:

    alt

    这是标准的C语言源文件,其程序的基本语法完全是ANSI C的语法结构。首先是头文件的包含语句,所有的源文件中必须包含mex.h,它完成了所有C语言MEX函数的原型声明,还包含了matrix.h文件,即对mx函数和数据类型的声明和定义。

    接下来是C语言MEX源文件的入口函数部分,这也是必需的部分,并且书写形式固定。括号里的4个变量分别表示输入参数的个数、输入参数、输出参数的个数和输出参数。

    需要注意的是,MATLAB 7.0的MEX源文件中不能包括任何汉字,否则会出现编译连接错误。

    上述MEX源文件编写完毕后,保存在MATLAB的当前工作路径下,名称为mexhello.c,接着在命令窗口键入以下指令:

    alt

    此命令对MEX文件进行编译,创建出MATLAB的MEX文件,可以在MATLAB命令行中运行下面的语句:

    alt


    注意:上述编译过程也可以在命令行提示符窗口中完成。


    需要注意的是MATLAB本身是一个高效的系统,编程简单,效率高,不到万不得已,建议不要使用MEX手段。

    15.1.2 编写C MEX文件

    编写MEX文件源程序时,要用到两类API库函数,即mx-库函数和mex-库函数,前者用于在C语言中创建、访问、操作和删除结构体mxArray,后者用于与MATLAB环境进行交互。有关这些库函数的详细说明可参看MATLAB的help文件。

    下面通过一个实例来演示C MEX的编写过程。

    【例15.2】生成随机数——执行MATLAB函数

    示例代码设置如下:

    alt

    alt

    本例的源程序中使用mexCallMATLAB函数调用了MATLAB的随机数产生函数rand。mexCallMATLAB函数的定义如下:

    alt

    其中前4个参数为需要输入到被调用函数中的输入、输出参数,而最后一个参数为被调用的函数名称。当执行command_name函数出现错误时,根据mexSetTrapFlag函数的设置进行错误处理,其定义如下:

    alt

    若输入参数为0,则将程序的控制权交给MATLAB,退出MEX函数的执行,若输入参数为1,则将程序的控制权交给MEX函数,继续执行MEX函数。例子中的第一次MATLAB调用是错误的,不存在rnd函数,程序如何执行将决定于flag值的设定。

    编译并执行randomnum.c,代码设置如下:

    alt

    不同的实例将会用到不同的mex函数,有关其他mex函数的使用,用户可以参看help说明和其他专门资料的例程。

    此外,MEX文件还可用Visual Studio来创建,适合习惯利用集成开发环境的程序员使用。

    15.2 创建Fortran语言MEX文件

    使用Fortran语言创建MEX文件的方法和过程与创建C语言MEX文件的方法和过程几乎一样,无非是使用的高级编程语言有所不同而已。Fortran语言在科学计算方面的应用比C语言要广泛,它的数值稳定性和多种数值变量是C语言无法匹敌的。

    本节主要介绍Fortran语言MEX文件的创建。

    15.2.1 Fortran语言MEX文件简介

    以一个简单的例程介绍Fortran语言MEX文件。

    【例15.3】简单的Fortran语言MEX文件——mexhello.c

    alt

    它的功能也是在MATLAB命令窗口输出一段文字。在M文件编辑器中输入完毕后,保存在当前工作目录下,名称为mexhello.f。然后编译运行:

    alt


    注意:在进行编译之前,一定要在MATLAB环境下完成MEX文件编译器的配置,本书例程中所使用的Fortran开发环境是Compaq Visual Fortran。


    与C MEX类似,首先是入口函数的声明部分(没有了头文件的包含语句),输入参数和输出参数的含义与C相同,然后是源程序的主体部分,进行数据的存取和内存的分配,调用相应的计算子程序或者函数。程序的结尾是Fortran的特别要求,必须有return和end关键字作为结束。

    MATLAB的数据在C中使用mxArray数据类型来表示,但是在Fortran中没有显性的定义该数据结构,而是通过一种所谓的“指针”类型数据完成Fortran和MATLAB之间的数据传递。MATLAB将需要传递的mxArray数据指针保存为一个整数类型的变量,例如在mexFunction入口函数中声明的prhs和plhs,然后在Fortran程序中,通过能够访问指针的Fortran语言mx函数访问mxArray数据,获取其中的实际数据。

    15.2.2 Fortran MEX文件示例

    【例15.4】创建稀疏矩阵

    alt

    alt

    本例的核心部分首先使用mxCreateSparse函数创建了稀疏矩阵的mxArray数据对象,然后分别使用mxGetIr、mxGetJc、mxGetPr3个函数获取稀疏矩阵的3个重要指针ir、jc和pr,这里是实数的矩阵,所以没有pi指针。接着使用mxCopy函数完成数据内存的复制。需要注意的是整数类型的数据拷贝,在MATLAB的API函数库中,有3个不同的函数用于整数类型数据的拷贝,分别是mxCopyInteger1ToPtr、mxCopyInteger2ToPtr和mxCopyInteger4ToPtr。同样,还有3个函数用于将指针数据拷贝给相应的整型数据,这里不再列举。具体程序编写过程中要针对具体的整数数据类型选取不同的拷贝函数。下面是编译运行该文件后的一些结果:

    alt

    15.3 MAT文件应用

    MATLAB与外界交互数据有直接输入输出法(用于数据量小的情况)、数据的M文件输入和diary文件输出法、输入输出数据的ASCⅡ文件法、低层IO指令读写数据法、读写数据的MEX文件法和MAT文件法等多种方法。其中MAT文件法是先用C或者Fortran编写一个专门的文件,实现原数据与MAT文件格式之间的相互转换,进而借助save,load实现MATLAB对原数据的读写。MAT文件是MATLAB数据存储的默认文件格式,由文件头和数据组成,文件扩展名是m.mat。

    【例15.5】save和load指令示例

    在MATLAB命令行窗口中,键入下面的指令:

    alt

    alt

    下面将介绍MAT文件的应用,所谓MAT文件的应用就是指读写MAT数据文件的C语言或者Fortran语言应用程序,它可以是MEX文件也可以是独立的可执行应用程序。为了便于读写MAT文件,MATLAB提供了响应的接口函数——mat函数,MAT文件应用程序就是利用这些mat函数完成MAT数据文件的读写工作。下面给出一个C语言MAT文件应用的例子,可从中了解MAT文件应用程序的基本结构和MAT文件应用的基本过程。

    【例15.6】在C语言MEX文件中创建MAT数据文件——mexcreatematfile.c

    示例代码设置如下:

    alt

    alt

    alt

    首先所有MAT数据文件应用程序的C语言代码中必须包含mat.h,它定义了mat函数的原型,并且包含了matrix.h头文件。接下来的代码和普通的MEX文件应用程序的代码没什么区别,然后用matOpen函数打开一个数据文件,再调用matPutVariable函数向MAT文件中写入数据。最后关闭MAT文件(matClose)并释放内存。编译链接生成MEX文件,然后运行以下代码:

    alt

    alt

    有关mat函数的详细说明可以参阅MATLAB的help文档,由于篇幅限制,不再讨论Fortran语言MAT文件的应用和集成开发环境下的应用。

    15.4 MATLAB引擎技术的应用

    MATLAB计算引擎应用程序的思想和MATLAB的MEX文件正好相反,MEX文件是在MATLAB环境下调用C或者Fortran语言程序的手段,而MATLAB计算引擎则是在C或者Fortran语言环境中调用MATLAB函数的方法。引擎函数本身用C或Fortran编写,在Windows平台上,它与MATLAB的通信是借助ActiveX进行的,它可运用于以下场合:

    · MATLAB在其他语言编制的应用程序中被当作数学库程序调用,充分利用MATLAB指令简单、计算可靠的优点。

    · MATLAB在专用系统中被当作计算引擎时用,前台是C语言等编写的GUI图形用户接口,后台由MATLAB执行各种复杂的计算分析,从而大大缩短了用户的开发时间。

    本节主要介绍如何调用MATLAB引擎函数,如何用C语言编写调用MATLAB引擎的源程序。至于如何编写Fortran语言源程序,可参阅help文档。

    【例15.7】简单的C语言计算引擎应用示例——simpleeng.c

    通过本例的程序,可以了解调用MATLAB引擎的源程序的一般结构;引擎函数的用法,这些函数都是以eng前缀开始的;MATLAB环境外数据与引擎函数的配合使用。

    · 编写源程序simpleeng.c

    示例代码设置如下:

    alt

    alt

    alt

    alt

    首先在代码的最开始包含了需要的头文件,在所有的C语言引擎应用程序中,都必须包含engine.h头文件,它声明了所有eng函数的原型,并且包含了matrix.h头文件,其他的头文件根据需要包含进去;然后声明了Engine类型的指针,该指针类似于打开文件时的文件指针,相当于计算引擎的接口句柄,有了这个指针就可以在C语言中执行MATLAB的指令了;最后完成代码后应该关闭计算引擎,通过engClose函数完成,它关闭指针释放内存。

    · 编译连接源程序

    采用类似于上一节编译MAT数据文件引用程序的方法来编译计算引擎程序,可以在MATLAB的命令窗口下,也可以在命令提示符窗口下进行。和生成MEX文件不同的是,生成MEX文件时,只要在MATLAB中完成编译器的配置工作就可以使用MEX指令完成编译,因为在配置编译器的时候需要将编译器的选项文件改名为mexopts.bat选项文件,并且拷贝到了系统环境目录下。但是在系统路径下mexopts.bat文件不能完成MATLAB计算引擎引用程序的编译,必须通过MEX命令行指定具体的选项文件才可以。代码设置如下:

    alt

    · 运行simpleeng.exe

    可以直接双击simpleeng.exe文件,也可以在MATLAB命令行窗口键入以下指令:

    alt

    这时操作系统启动一个MATLAB进程(只包含MATLAB的命令行窗口),如图15-1所示。

    alt

    图15-1 计算引擎启动的MATLAB会话窗口

    这时在Windows的命令行提示符中的显示如图15-2所示。

    alt

    图15-2 Windows命令行提示符窗口

    如果在图15-1所示的窗口中键入下面的指令:

    alt

    在命令提示符行中按任意键继续执行,重复出现提示信息后,回到新启动的MATLAB会话窗口,键入下列指令:

    alt

    可见由于代码的执行A变成了Fibonacci数列的部分元素。然后再按任意键,则执行关闭引擎的命令,MATLAB会话自动退出运行。由上例可以看出,MATLAB计算引擎应用程序的基本工作流程如下:

    打开计算引擎(engOpen)→设置数据(engPutVariable)→执行MATLAB指令(engEvalString)→获取计算结果(engGetVariable)→关闭计算引擎(engClose)。

    有关eng函数的详细说明可以参看help文档。

    15.5 MATLAB的Java接口

    Java语言是一种流行的面向对象的高级编程语言,能够完成各种类型的应用程序开发,MATLAB和Java之间的关系是非常密切的,从5.3版本开始,MATLAB中都包含了Java虚拟机。在MATLAB中可以直接调用Java的应用程序,新版本的MATLAB工具箱中就包含了很多使用Java语言开发的图形用户界面工具,例如COM Builder的用户界面comtool等。利用MATLAB的Java接口可以完成下列工作:调用Java API类和包,完成核心功能;调用第三方Java类;在MATLAB环境下创建Java对象;通过Java语法或者MATLAB语法使用Java对象的方法;在Java对象和MATLAB之间交互数据。

    Java可以填补MATLAB的一些功能上的空白,特别由于Java自身的优势,完全可以通过Java语言获取大量的来自互联网或者数据库的数据,而MATLAB自身的优势是进行数据分析、科学计算,两者有机结合,充分发挥各自的优势,将极大提高工作效率,节约开发时间和成本。

    在MATLAB中键入下列指令可以查看当前MATLAB使用的Java虚拟机的版本:

    alt

    可根据此版本选择JDK(Java开发包)的版本,避免出现不兼容的现象。

    15.5.1 Java接口应用

    Java是一种面向对象的高级编程语言,其中类和对象是最基本的概念,如果要创建对象,则必须有相应的类存在。Java语言除了最基本的关键字以外,还提供了大量的预先编制好的类,应用Java就是通过Java语言的类完成各种功能。一般可将这些类分为3种:Java内建类(由Java语言本身提供的类和类包);第三方定义类(一些商业化或者免费的应用于专门领域的类包);用户自定义类(从已有的类派生出来或者直接开发的新类)。

    不同的类组合在一起构成类包,这些类包一般安装在系统路径下面,通过系统变量classpath定义给操作系统。在MATALB中,其系统路径下存在一个文本文件——classpath.txt,该文件定义了MATLAB环境可以直接引入的MATLAB包。一般该文件位于%MATLABROOT%\toolbox\local路径下。默认情况下,classpath文件只是定义了Java内建类包和由Mathworks公司提供的工具箱类包,如果需要使用第三方或者用户自定义类包,则需在文件中添加,其使用规则是:用户自定义类库添加直到父目录的完整路径,包添加直到最高级父目录的完整路径,JAR文件中的类库添加完整的路径、完整的文件名。引入Java类包后就可直接创建Java对象。

    在MATLAB中创建Java对象有直接用Java类定义或用javaObject函数创建两种方法。下面举例说明。

    【例15.8】在MATLAB中键入下列指令

    示例代码设置如下:

    alt

    在上述代码中,都使用了完整的Java类的名称,可以在Java语言中使用import命令导入必要的类包,这样声明对象的时候就不用给出完整的类的名称了,在M语言中也是如此,如上例,也可写作下面的代码:

    alt

    【例15.9】设置Java对象的属性

    示例代码设置如下:

    alt

    本例采用了两种方法设置了不同对象的同一个属性。修改Java对象的属性还可以像操作句柄图形对象一样使用set或者get函数。而且在M语言中创建的Java对象可以通过save和load命令保存到MAT数据文件中和加载到当前的工作空间中。

    在应用Java对象时需要注意Java对象在MATLAB中属于一类特殊的数据类型,几乎所有的MATLAB数据都可以向Java数据对象转变,但是Java的对象一般不能直接参与MATLAB的数据运算,需要进行相应的类型转换才可以。

    【例15.10】Java的数据

    示例代码设置如下:

    alt

    最后在MATLAB中创建Java的数据,需要用到一个函数:

    alt

    其中x1~xn是数组每一维的尺寸。

    15.5.2 应用示例

    在M语言中应用Java类的主要目的之一就是充分利用Java语言的网络功能,例如读取网络上的信息等。

    【例15.11】读取URL信息

    示例代码设置如下:

    alt

    本例大部分都是Java的语法结构,首先创建了Java的URL类对象,然后利用Java的I/O流的功能从互联网的网页上读取了信息,这里将互联网的网页看作纯文本文件读取,最后三行每一句都读取文本中的一行。运行结果如下:

    alt

    15.6 MATLAB中的DDE技术

    动态数据交换DDE(Dynamic Data Exchange)是允许各Windows应用程序间交换数据的通信机制。Windows平台上的MATLAB作为一个应用程序,也具有借助DDE与其他应用程序通信的功能。

    15.6.1 关于DDE的一般性说明

    应用程序可以借助DDE通话实现彼此间的通信。请求建立对话的应用程序称为客户(Client),而响应对话请求的应用程序被称为服务器(Server)。

    当客户应用程序创建DDE对话时,必须识别被呼叫服务器的两个DDE参数:服务名(Service name),即被请求对话的应用程序名;话题(Topic),即对话主题。这两个参数的组合构成了区分不同对话的惟一标识。

    每个作为服务器的应用程序都有惟一的服务名。它们通常就是该应用程序的(不带扩展名)可执行文件名。比如matlab是MATLAB的服务名。

    15.6.2 DDE中的MATLAB服务器

    视客户应用程序的具体情况而定,客户可以采用不同方法访问作为服务器的MATLAB。假如客户应用程序能够提供管理DDE对话的函数或宏,则必须充分利用那些函数和宏;假如客户应用程序是自编的,则最好利用MATLAB引擎库或直接利用DDE。MATLAB用作服务器时的工作原理如图15-3所示。此时客户应用程序是通过DDE函数与MATLAB DDE服务器模块进行通信的。客户DDE函数可以由客户应用程序提供,也可以由MATLAB引擎库提供。

    alt

    图15-3 DDE MATLAB服务器工作模式

    DDE对话内容由一组预习规定的参数名称组成。当MATLAB作为DDE服务器使用时,所能选用的具体名称和它们间的层次关系如图15-4所示。由图可见,MATLAB有两类“话题”System和Engine。而每类话题又包含几个不同的内容细节。例如,Engine话题就其内容性质而言又分为两类,即客户把指令发给MATLAB计算(EngEvalString)和客户向MATLAB索取结果;第二类由于数据性质的不同,又分为文字结果(EngStringResult),图形结果(EngFigureResult),以Text格式或XL表格式把对话内容约定为索取某个名称的矩阵。

    alt

    图15-4 DDE中MATLAB作为服务器使用时定义对话的参数名称层次表

    15.6.3 DDE中的MATLAB客户

    当MATLAB以客户身份建立DDE通信时,其工作原理如图15-5所示。图中的客户模块可由一系列的函数构成(见附录),本节将通过一个例子展示各指令间的配合使用。

    alt

    图15-5 MATLAB作为客户时的DDE原理图

    【例15.12】设计一个DDE对话程序。MATLAB作为客户,Excel作为服务器,本例演示DDE的创建和关闭,热连接的建立和使用。程序(dde_disp.m)如下:

    alt

    在Excel开启的前提下,运行上述程序将产生如图15-6和图15-7所示的两个界面。

    alt

    图15-6 运行后生成的图形

    alt

    图15-7 运行后产生的表格数据

    将Sheet3表格中的A1元素修改为-9,如图15-8所示,由于该数据区和所画曲面之间建立了热连接,所以可以观察到图形发生了如图15-9的变化,在曲面正前方处产生了一个向下的尖角,这就是热连接的作用使得图形曲面随表格数据的变化同步变化。

    所建立的热连接和对话通道若不再使用,则应该关闭节省资源。本例在图形窗上为关闭热连接和对话通道设立了专门的菜单如图15-10所示。如果选中其中的“关热连接”选项,则以后图形将不会随数据表格的变化而变化。

    alt

    图15-8 改变A1的值图

    alt

    图15-9 曲面产生相应的下尖角图

    alt

    图15-10 为关闭热连接和对话通道设计的菜单


    注意:假如建立的通道没有正常关闭,那么同一个程序的再运行可能出现通道识别错误。在这种情况下,改变通道代号或者冷启动计算机可能克服故障。


    15.7 MATLAB中的ActiveX技术

    15.7.1 关于ActiveX的一般性说明

    ActiveX是一种基于Microsoft Windows操作系统的组件集成协议,是各种面向对象技术的集合。这些技术共有的基础是“组建对象模型(Component Object Model)”,简称COM。借助ActiveX,开发商和终端用户就能把来自不同商家的ActiveX组件无缝地集成在自己的应用程序中,从而完成特定的目的。不仅节省了开发时间,而且有效地避免了低水平的重复开发。

    每个ActiveX都支持一个或多个赋名的界面,而界面是一组逻辑相关方法、属性和事件的组合。方法类似于请求对象实现某动作的函数;属性是对象持有的状态参数;事件是将控制交回客户(Client)的通知,与图形句柄的callback相似。MATLAB支持两种ActiveX技术,即ActiveX控件封装集成和ActiveX自动化。ActiveX控件是指那些可视、能编程的集成于ActiveX容器的应用组件,比如Microsoft Internet Explorer和Web Browser control。

    ActiveX自动化使得MATLAB能施控和受控于其他组件。当MATLAB受控于其他组件时,表现为自动化服务器(Automation server),其功能包括:在MATLAB空间中执行指令,与MATLAB空间直接交换数据;当MATLAB控制其他组件时,表现为自动化客户(Automation client),其功能是MATLAB借助M文件指示和操纵自动化服务器。

    MATLAB自动化客户的功能仅是MATLAB ActiveX控件封装集成功能的子集。所有的ActiveX控件都是ActiveX自动化服务器,但不是所有的自动化服务器一定是ActiveX控件。那些不是控件的自动化服务器将不可被物理地、可视地镶嵌于客户应用中。MATLAB本身是服务器而不是控件,所以不能被镶嵌在其他客户应用中。然而,由于MATLAB是控制容器,所以其他的ActiveX控件可以内嵌在MATLAB中。

    15.7.2 MATLAB的ActiveX自动化

    1.MATLAB ActiveX自动化控制器(客户)

    如果要MATLAB通过ActiveX自动化客户支持调用其他ActiveX组件,那么必须先查阅该ActiveX组建的相关文件,从中得到该组件的名字(ProgID)、该组件所采用的接口名、方法(Method)、属性(Property)和事件(Event)等。

    ActiveX的创建和操作函数见附录。指令actcontrol用于创建ActiveX自动化客户支持。该指令运行后将引出指定组件名(比如Excel、Application)的对象默认界面。通过该对象属性的获取和设置、方法的激活,就可以改变该对象的界面和行为。

    【例15.13】MATLAB以自动化客户的资格通过M脚本文件把Microsoft Excel用作自动化服务器。本例演示调用自动化服务器的基本指令。Excel默认界面的开启;增添工作簿(Workbook);改变激活的当前页(Worksheet);MATLAB与Excel之间的数据传递;Excel的数据保存。(图15-11给出了第21行程序执行前产生的Excel界面)

    程序(actexcel.m)如下:

    alt

    alt

    图15-11 第21行程序执行前产生的Excel界面

    2.MATLAB ActiveX自动化服务器

    通过MATLAB ActiveX自动化服务器,用户可以在自己的应用程序中执行MATLAB命令,并可以与MATLAB的工作空间交换数据。将MATLAB作为服务器使用时,用户必须首先查阅希望使用自动化服务器的应用程序的文档。查明如何在控制器中开启自动化服务器;MATLAB ActiveX对象在系统注册表中定义的名字,即ProgID。通常ProgID取以下两个名字中的一个:MATLAB.Application(将启动的MATLAB自动化服务器作为“共享”服务器);MATLAB.Application.Single(将启动的MATLAB自动化服务器作为“专用”服务器独享)。