Matcom是mathTools公司推出的最早的Matlab到C++的编译器。后来,由于Mathtools被Matlab公司收购,Mtacom对Matlab 5.3以后的版本就没有推出新的版本。相比Matlab自带的编译器Compiler,用Matcom转化代码要简单和方便得多;且对于采用C++的工程和研究人员来说Matcom的C++矩阵库(Matrix Lib)依然有非常大的利用价值。 通过Matcom连接M函数这类脚本语言或者高级算法语言有三种办法:—是将M文件编译成C++代码,然后在C++工程中插入这些代码,最后编译成为独立的可执行程序;二是直接在C++程序中使用Matcom提供的Matrix<lib>,方法与一相似,但常用。最后一种是利用MIDEVA直接生成EXE文件,然后在VC中通过shell调用,方法简单,但通用性差,仅适用于VC中调用Matlab实现图形显示的场合。 Mideva软件平台本身的功能相当强大,提供近千个Matlab的基本功能函数,通过必要的设置,就可以直接实现与C++的混合编程,而不必再依赖Matlab;同时,Mediva还提供编译转换功能,能够将Matlab函数或编写的Matlab程序转换为C++形式的DLL,从而实现脱离Matlab环境对Matlab函数和过程的有效调用,这样就有可能实现对Matlab强大的工具箱函数的利用。 Mideva的缺点是C++与Matlab混合编写的应用软件必须携带必要的DLL,从而增大了软件的体积(约4M),同时也不能对所有的Matlab函数提供支持,例如采用类库进行设计的部分函数。 本节将以VC++6.0和Matcom为例,1,详细介绍如何利用Matcom进行VC++与Matlab的联合编程(即一);2 ,介绍一下在VC++中怎样使用Matcom C++矩阵库(即二)。 1. 目前,Matcom的最高版本为4.5。首先安装Matcom 4.5,如下图 : 安装Matcom前要已求安装VC++6.0。在安装过程中出现选择编译器对话框,选择”是” 如下图: ![](https://i-blog.csdnimg.cn/blog_migrate/9559aa5a5938c9d4ea0d101a4ad45e77.png) 出现选择是否安装了Matlab时,如果本机上安装的是Matlab 5.3版本,可以选择“是(Y)”确认,因为Matcom4.5不支持Matlab 6.1以上的版本。其他选项采用默认设置。Matcom可以独立于Matlab运行,但需要外部的C++编译器,指定Matlab的位置是为了让编译文件中需要的一些系统函数找到路径用的。 安装完成后,在“<Matcom 根目录>lib”下,可以找到使用MatcomC++矩阵库(Matrix Lib)的头文件matlib.h和v4501v.lib文件,在Windows操作系统目录的system32目录下,可以找到使用MatcomC++矩阵库的动态链接库文件v4501v.dll。启动界面MIDEVA,如下图。MIDEVA集成开发环境包括命令行窗口、变量列表窗口、命令列表窗口和编译链接信息窗口等几部分,并有详细的帮助文档。 ![](https://i-blog.csdnimg.cn/blog_migrate/8e26efa7ffab542977a9ed9a3d7b63cd.png) Matcom命令输入方法与Matlab相同。如果安装在中文版操作系统时,输入命令前加一空格,否则显示为乱码。 下面详细介绍如何将m文件编译后放入VC++中。 启动MIDEVA ,File->New,新建如下huatu.m文件。 m文件保存的默认位置为:matcom安装目录matcom45,生成的C++文件保存的默认位置为matcom安装目录matcom45Debug,本例matcom安装目录为C盘 即 C:matcom45Debug,在该目录下将会产生huatu.h、huatu.cpp、huatu.r 、huatu.obj文件。 在VC++中用MFC Wizard(exe)创建一个基于对话框名为Example的工程。在面板上添加一个ID为IDC_BUTTON1按扭。 C:matcom45Debug目录下的huatu.cpp文件的内容拷贝到void CExamleDlg::OnButton1()如下, void CExampleDoc::OnButton1() { dMm(x); dMm(y); #line 1 "c:/matcom45/huatu.m" call_stack_begin; #line 1 "c:/matcom45/huatu.m" _ x = colon(-2.0,0.1,2.0); #line 2 "c:/matcom45/huatu.m" _ y = power(x,2.0); #line 3 "c:/matcom45/huatu.m" _ display( plot((CL(x),y)) ); call_stack_end } 将C:matcom45lib下的matlib.h 和v4501v文件和C:matcom45debug下的huatu1.h文件拷贝到工程Example目录下,然后在VC中将库文件和头文件加入到工程中:工程->添加工程->Files,选择刚刚拷贝到Example目录下的matlib.h 、v4501v和huatu1.h文件 五,在ExamleDlg.cpp中加入如下代码: #include "matlib.h" #include "huatu.h" 在void CExamleDlg::OnButton1()中分别添加一个初始化类库调用函数”initM(MATCOM_VERSION)”和一个结束类库调用函数”exitM()”如下。 void CExampleDoc::OnButton1() { initM(MATCOM_VERSION) dMm(x); dMm(y); #line 1 "c:/matcom45/huatu.m" call_stack_begin; #line 1 "c:/matcom45/huatu.m" _ x = colon(-2.0,0.1,2.0); #line 2 "c:/matcom45/huatu.m" _ y = power(x,2.0); #line 3 "c:/matcom45/huatu.m" _ display( plot((CL(x),y)) ); call_stack_end exitM() } 运行程序,点击画图按扭得图: ![](https://i-blog.csdnimg.cn/blog_migrate/534cee3c62c8c9c00ba41f11fb9413a5.png) ![](https://i-blog.csdnimg.cn/blog_migrate/534cee3c62c8c9c00ba41f11fb9413a5.png) Matcom C++ 矩阵库的初始化和释放是成对出现的,在初始化时,调用函数initM(Matcom_VERSION),在需要释放的时候,调用函数exitM()即可。Matcom C++ 矩阵库的初始化需要一定的时间,为了加快程序的执行速度,应尽量减少Matcom C++ 矩阵库的初始化的次数。所以开发人员应仔细考虑Matcom C++ 矩阵库生存周期的长度,在Matcom C++ 矩阵库生存周期的开始初始化C++库,在生存周期结束的时候,释放 C++库。这样虽然会占用一定的内存,但是会提高程序运行的速度。 Matcom不但可以生成C++文件,而且还可以生成exe文件和dll文件。如图所示: ![](https://i-blog.csdnimg.cn/blog_migrate/1e53ed47578e10e885862f00dcf48683.png) 2.下面通过一个例子来说明Matcom C++ 矩阵库在Visual C++ 6.0中使用的过程: 在Visual C++ 6.0中,新建一个Win32 Console工程,如下图。实际上在任何类型的 C++工程中都可以使用Matrix<lib>,为了简单我们以控制台程序为例。 ![](https://i-blog.csdnimg.cn/blog_migrate/e8143b62a02b1e42f2ebdeda62d78e28.png) 二.设置工程,打开Project|Setting的link标签,作如下修改见下图: ![](https://i-blog.csdnimg.cn/blog_migrate/f32a12f52f2217ef1e267e5c30d50adf.png) 打开C/C++标签,作如下修改见下图: ![](https://i-blog.csdnimg.cn/blog_migrate/51a19a61ed5c3f72607467ceb0d50db4.png) 加入头文件matlib.h,看是否成功?不成功检查设置! 在Example.cpp中输入如下程序 #include "stdafx.h" #include "stdio.h" #include "matlib.h" int main(int argc, char* argv[]) { initM(Matcom_VERSION); Mm a; a=rand(3,3); display(a); exitM(); return 0; } 输出结果: ans (3x3)=9 double elements real (72 bytes)= 0.9501 0.4860 0.4565 0.2311 0.8913 0.0185 0.6068 0.7621 0.8214 在这说明一下,Matcom C++矩阵库采用面向对象的设计风格,矩阵数据和操作都封装在类Mm中。当需要创建矩阵的时候,只要声明一个Mm对象实例即可。如:Mm a; 关于Matlab所生成的COM组件,还有以下几个在实践中较为有用的说明: 1. 对于用于生成COM的任何一个Matlab函数,在COM组件中即为一个COM的方法,而Matlab函数中的全局变量(global)则为COM组件的一个属性。这一点对于神经网络编程中颇为有用,比如说,在ANN训练结束后,做仿真(simulate)时,我们需要调用Matlab生成的COM组件,但是,显然我们不能每调用一次COM就读一次ANN的配置(如权重、偏置等项目的值),也不能在VC中出现Matlab的结构体或者类。在这种情况下,我们就可以专门做一个Matlab函数,使用该函数调入ANN配置文件(一般为.mat文件)。而把ANN的配置量声明为全局变量,则可以在仿真函数中直接使用该变量。就像以下的示例: function y = sim_ann(x) global net y = sim(net, x); function LoadAnnParam global net % AnnMat.mat文件中存储了net变量 load AnnMat net 在VC中调用时,设COM对象为comObj,则有以下调用方式: comObj.LoadAnnParam(); //载入ANN参数 for(int I = 0; I < n; I++) comObj.sim_ann(1, x, y); //多次仿真ANN 2. 在Matlab中可以自定义数据类型,也就是VC中的类,但是这在生成COM组件时,会出现在load新类的对象时Matlab不认识该类型。这种情况下,我们可以在load该类以前,先初始化一个同名的该类型的对象。比如我们有NewClass这种新类,要load进来一个该类型的名字为NewObj的对象,对象的初始化函数为InitNewClass,则可以: NewObj = InitNewClass; Load mat_file NewObj; 3. 另外,在编程过程中曾遇到过这种情况,在生成的COM接口中如果输出变量为结构体时,有时会出现莫名其妙的峰鸣器常鸣的效果。这种情况经过多方查找无法找到原因,如果各位读者在使用中出现类似情况,可以从这个方面考虑问题的解决方法。
|