Matlab与VC++混合编程

Matlab与VC++混合编程主要有三种方式:Matlab引擎方式、Matlab编译器及COM组件。

一、    Matlab引擎方式

Matlab引擎采用客户机/服务器(Client/Server)的方式,提供了一组Matlab API函数,通过调用这些函数实现以用程序进程之间的数据传递。VC程序作为前端客户机,向Matlab引擎传递命令和数据,并从Matlab引擎接受数据信息,实现动态通信。采用这种方法几乎能利用MATLAB全部功能,但是需要在机器上安装MATLAB软件,而且执行效率低,因此在实际应用中不采用这种方法,在软件开发中也不可行。

二、    Matlab编译器

MATLAB Compiler可以将M语言函数文件自动转化产生独立应用程序或者软件组件,生成的组件或者独立应用程序可以与其他用户共享。使用MATLAB Compiler创建的独立应用程序或者软件组件能够完全脱离MATLAB环境。

MATLAB Compiler能够显著的缩短桌面应用程序的开发时间,仅仅通过简单的指令就可以将M语言函数转变为独立的应用程序或者软件组件,然后将它们打包发布给最终用户。这里所指的利用M语言开发的MATLAB应用程序可以包括数学计算、图形应用和GUIDE开发的图形界面等,而最终用户根本不需要拥有MATLAB。

特点:

1、自动将M语言函数文件转换为可执行应用程序,脱离MATLAB环境

2、简单易用的发布过程

3、支持所有MATLAB的M语言特性,例如MATLAB对象、Java对象等等

4、支持大多数工具箱函数,允许将MATLAB基本算法免费发布使用强大功能

 5、用户可以利用MATLAB集成环境开发自己的算法原型和应用程序,然后利用MATLAB Compiler将开发的算法发布给最终用户,最终用户可以通过可执行应用程序或者软件组件应用开发完好的算法。用户在进行算法维护的时候无需针对C代码进行操作。

算法开发仅仅需要三个步骤:创建算法、转化应用程序、应用程序发布。

(1)创建算法

MATLAB本身是一种集成化的算法开发环境,它提供了各种工具用于完成算法快速原型的开发、测试。其中包括了高级的基于矩阵运算的向量化算法语言M语言,并且内建了大量用于数学计算、数据分析和图形可视化的算法函数。MATLAB开发工具提供了语言编辑器、调试工具和性能分析器,并且可以利用交互式图形界面开发工具开发自定义的图形界面工具。

(2)转化应用程序

使用MATLAB Compiler可以将开发好的M语言算法函数转变成为:

独立可执行应用程序

C/C++算法共享库

软件组件,例如COM对象或者Excel插件

独立可执行应用程序

MATLAB Compiler可以自动地将MATLAB应用程序转变为独立可执行应用程序;自动确定相关的MATLAB函数 ;生成C/C++接口代码文件 ;将所有相关的文件打包压缩保存在单一压缩文件中;可在最终的应用程序中集成用户的C或C++代码

(3)算法函数库

使用与创建独立可执行应用程序相同的指令就可以创建MATLAB函数库。MATLAB  Compiler将自动创建相应的头文件和共享库文件,以便集成自定义的C/C++代码文件,最终完成应用程序的开发。

(4)应用程序发布

通过MATLAB Compiler完成应用程序的发布之后,可以将应用程序打包、发布给任意的最终用户。MATLAB Compiler提供了相应的应用软件可以将运行应用程序必需的库文件打包。

三、    COM组件

COM(Component Object Model,组件对象模型)是以组件为发布单元的对象模型,是一系列面向对象技术和工具的集合。

由于COM是建立在二进制级别上的规范,所以组件对象之间的交互规范不依赖于任何特定的语言。

MATLAB提供了COM生成器。COM生成器提供了实现MATLAB独立应用的一种新途径。它能把MATLAB开发的算法做成组件,这些组件作为独立的COM对象,可以直接被C++、VB、VC、C#、JAVA或其他支持COM的语言所引用,只要相应的MATLAB编译器和C/C+ +编译器都已经安装及配置成功,MATLAB COM编译器即可开始使用,并不需要特别的设置。

该方法实现简单,通用性强,而且几乎可以使用MATLAB的任何函数(注意:不支持脚本文件,脚本文件使用时要改为函数文件),因此在程序较大、调用工具箱函数或调用函数较多时推荐使用。Matlab的COM 编译器是在Matlab6.5中才开始提供的一个新工具,从Matlab7.0起,这个产品改名为MatlabBuilder for COM。基于COM的混合编程方法也是Mathworks公司推荐使用的方法。

以上3种方法中,采用Matlab引擎方式,应用程序整体性能好,Matlab引擎支持功能全面,但需要Matlab后台运行,不能脱离Matlab 环境。而MCC方法和COM组件方法均可以脱离Matlab环境,应用程序运行效率高,利于软件的开发。

利用COM组件实现matlabVC++混合编程实例

(1)创建COM组件。在MATLAB命令窗口输入命令deploytool,打开DeploymentTool对话框(图1)。点击 File->New Project,会弹出一个新工程设置对话框,选择如图2,填入组件名和类名,完成之后点OK,完成新工程的创建。

(2)添加文件到组件。执行完第一步后回到Deployment Tool界面。点击刚才创建的工程,单击Add files按钮,在随后出来的文件打开对话框中选择正确的文件名,将M文件添加到新建的组件类中。将这个M文件添加到Deployment Tool中,需要注意的是,function的名称很重要,这个名称是以后调用动态链接库的名称。在创建Deployment Tool新文件时,文件名称也要和function中的名称一样(图3)

(3)编译工程。点击Build->COM Object编译当前工程的COM组件,同时也完成在计算机上注册了该组件,这样它就可以像其他COM组件一样在VC++中使用了。编译完成以后在用户设置的项目目录下会产生两个子文件夹src和distrib和一个prj文件,distrib里包含供用户最终发布使用的COM组件。src中则包含用户在调用动态链接库函数是所要用到的源文件和头文件,以及接口文件等,将其中的try_idl_i.c,try_idl.h,mwcomtypes.h三个文件复制到接下来所建立的应用程序文件夹下。

(4)编译完成后,创建MFC应用程序。在Visual C++中创建一个基于对话框的MFC应用程序,

取名fun,接受所有默认设置。设计对话框,见(图3.15)

 

在后台程序部分要包括编译成的几个文件

#include "..\try\src\try_idl.h" 
#include "..\try\src\try_idl_i.c"

这两个文件是由deploytool自己编译产生的。

在源文件中加入#include "try_idl_i.c",在头文件中加入#include "try_idl.h"。

与此同时还要编写调用动态链接库函数的程序,如下:

VARIANT data,BE;
    VariantInit(&BE);
    VariantInit(&data);     
    HRESULT hr = CoInitialize(NULL); 
    hr=CoCreateInstance
    (CLSID_tryclass,NULL,CLSCTX_INPROC_SERVER, IID_Itryclass,
        (void **)&p1);
    int outputNum=1;//输出参数变量数目
    hr=(p1 -> fun(outputNum,&BE,data));
    m_edd=BE.dblVal;
    ::CoUninitialize();

(5)打包组件及MCR 。为了把编译后产生的COM组件发布到其他计算机上注册。选择Component->package component命令,deploytool将会把发布该组件所需要的所有文件打包到一个和工程同名的可执行文件中。在打包组件的时候最好选择包含MCR,这样在打包文件中就会包含MCR的安装文件。打包后将会在distrib中产生名为try_pkg.exe的可执行文件,这是一个可以自解压的ZIP压缩文件。其中包含4个文件:_install.bat文件、 try.dll文件try.ctf文件,把产生的try_pkg.exe文件复制到需要发布的计算机上后运行。结果将会把这四个文件解压,并执行_install .bat ,查看_install.bat的内容后可以发现_install.bat将会运行MCRInstaller.exe来安装MCR,并且在系统中注册组件文件。

 

//当matlab中fun函数输出的BER是一个一维数组情况(多维数组一样)。
Fun() 
{
    // TODO: Add your control notification handler code here
    VARIANT BE,para1;
    VariantInit(&BE);
    VariantInit(&para1);
    BE.vt=VT_ARRAY | VT_R8;
    para1.vt=VT_R8; 

    SAFEARRAYBOUND bound [1];
    bound[0].cElements=3;
    bound[0].lLbound=0;
    BE.parray=SafeArrayCreate(VT_R8,1,bound);
    para1.dblVal=1000;
    HRESULT hr = CoInitialize(NULL); 
    Ifuncclass  *pIfuncclass;     
    hr=CoCreateInstance
        (CLSID_funcclass,NULL,CLSCTX_INPROC_SERVER, IID_Ifuncclass,
        (void **)&pIfuncclass);
    hr=(pIfuncclass -> func(1,&BE,para1));//1表示输出变量只有一个
    double *matrix,*pDest;
    matrix = new double [3];
    SafeArrayAccessData(BER.parray,(void**)&pDest);
    memcpy(matrix,pDest,3*sizeof(double));
    SafeArrayUnaccessData(BER.parray);
    SafeArrayDestroy(BER.parray);
    delete [] matrix;
    ::CoUninitialize();
}
Matrix中存储着输出的一位数组值!
posted @ 2012-05-29 22:35  renhang888  阅读(1366)  评论(0编辑  收藏  举报