前言
这是刚毕业时做项目时使用的VC MATLAB的混合内容,可以与大家分享。如果有什么问题,请批评。(大卫亚设)。
VC+MATLAB混编主要有两种方式:
第一种是运用MATLAB引擎,该方法的优点是在转成VC代码的时候只需要使用固定函数,然后将MATLAB代码完全复制,最后将VC和MATLAB的变量转换接口写好就可以了。缺点是需要安装整个MATLAB,依赖于MATLAB的自启动,而且程序运行效率较差。
第二种是应用MATLAB自带编译器,将函数编译成DLL和LIB文件,供VC程序调用。该方法优点是VC程序可以直接调用生成库文件里的函数,只需将VC程序里的变量转换成MATLAB函数需要的变量类型即可,而且程序运行效率较好。缺点不便于调试。
1. MATLAB引擎
1.1. 在64位win7操作系统下使用MATLAB2012b引擎的配置
1.1.1添加环境变量
Path变量中添加C:\Program Files\MATLAB\R2012b\bin\win64,如图1-1到图1-5所示。注意:添加完之后一定要重启计算机。
图1-1 添加环境变量-1
图1-2 添加环境变量-2
图1-3 添加环境变量-3
图1-4 添加环境变量-4
图1-5 添加环境变量5
1.1.2 X64平台配置
在VS中需要添加MATLAB引擎环境的工程中设置成x64平台。进入“配置管理器”,增加x64平台,如图1-6到1-8所示。
图1-6 X64平台配置-1
图1-7 X64平台配置-2
图1-8 X64平台配置-3
1.1.3 添加头文件和库文件
到项目属性中的C++目录中:
包含目录增加:C:\Program Files\MATLAB\R2012b\extern\include
库目录增加:C:\Program Files\MATLAB\R2012b\extern\lib\win64\microsoft
步骤如图1-9到图1-13所示。
最后添加上添加使用MATLAB引擎和函数需要的库文件和头文件:
#include “mat.h”
#include “engine.h”
#progma comment(lib,”libmx.lib”)
#progma comment(lib,”libmat.lib”)
#progma comment(lib,”libeng.lib”)
如图1-14所示
图1-9 添加头文件和库文件-1
图1-10 添加头文件和库文件-2
图1-11 添加头文件和库文件-3
图1-12 添加头文件和库文件-4
图1-13 添加头文件和库文件-5
图1-14 添加头文件和库文件-6
1.2. 使用MATLAB引擎VC与MATLAB变量转换说明
1.2.1 启动MATLAB引擎
在VC中使用MATLAB引擎首先要启动MATLAB引擎,代码如下:
Engine* ep; //定义MATLAB引擎指针。
If (!(ep=engOpen(NULL))) //测试是否启动MATLAB引擎成功。
{
AfxMessageBox(“Can’t start Matlab engine”);
}
1.2.2 写MATLAB函数命令
在VC使用MATLAB引擎中,写MATLAB语句非常简单,例如写一句MATLAB语句
“Figure,imshow(I)”,在VC中只要写成“engEvalString(ep,”Figure,imshow(I);”);”。
当MATLAB语句较长的时候或者有FOR循环或者IF语句的时候,可以将MATLAB代码写在一个engEvalString函数里,用“\”换行。举例如下:
MATLAB代码:
for i=1:5
for j=1:5
I(i,j)=1;
end
end
VC代码写成:
engEvalString(ep,”for i=1:5;\
for j=1:5;\
I(i,j)=1;\
end;\
end”);
1.2.3 VC与MATLAB混编举例
Void Detect(IN BYTE* pHBlob,BYTE* pLBlob,OUT BYTE* pBlob)
{
int iWidth=300;
int iHeight=300;
//定义MATLAB函数要使用的三个变量
mxArray* mxpHBlob=NULL;
mxArray* mxpLBlob=NULL;
mxArray* mxpBlob=NULL;
//给MATLAB输入两个变量分配空间
mxpHBlob=mxCreateNumericMatrix(iWidth,iHeight,,mxUINT8_CLASS,mxREAL);
mxpLBlob=mxCreateNumericMatrix(iWidth,iHeight,,mxUINT8_CLASS,mxREAL);
//将VC输入的变量地址拷贝给MATLAB输入变量
memcpy((void*)mxGetPr(mxpHBlob),(void*)pHBlob,iWidth*iHeight);
memcpy((void*)mxGetPr(mxpLBlob),(void*)pLBlob,iWidth*iHeight);
//将MATLAB输入变量传递到MATLAB中
engPutVariable(ep,”HBlob”,mxpHBlob);
engPutVariable(ep,”LBlob”,mxpLBlob);
//执行MATLAB函数
engEvalString(ep,”Blob=ImgRestruction(HBlob,LBlob);”);
//获得MATLAB函数输出变量
mxpBlob=engGetVariable(ep,”Blob”);
//将将MATLAB函数输出变量传递给VC函数输出变量
memcpy((void*)pBlob,(void*)mxGetPr(mxpBlob),iWidth*iHeight);
//销毁MATLAB变量矩阵空间
mxDestroyArray(mxpHBlob);
mxDestroyArray(mxpLBlob);
mxDestroyArray(mxpBlob);
return;
}
注意:自己写的MATLAB函数一定要放在..\R2012b\bin的目录下。
2. Matlab生成动态库
2.1. MATLAB生成动态库步骤
点击MATLAB Compiler,提示如图2-1所示,新输入一个工程名,类型选择C++共享库。第一次使用matlab生成动态库要安装编译器,如图2-2所示,在matlab中的Common Window窗口中输入mbuild –setup,然后提示选择一个编译器,依据自己需要选择,在项目里我们选择2。然后再MATLAB右端Build选项里点击Add files,选择需要编译的m文件,点击按钮进行编译,如图2-3、2-4所示。最后会在..My Document\Matlab\文件夹下生成一个m文件的文件夹,将其中生成的.lib、.dll、.h文件(如图2-5所示)拷贝到需要调用MATLAB动态库函数的VC工程目录下,即完成Matlab生成动态库的步骤。
图2-1 MATLAB生成动态库-1
图2-2 MATLAB生成动态库-2
图2-3 MATLAB生成动态库-3
图2-4 MATLAB生成动态库-4
图2-5 MATLAB生成动态库-5
2.2. VC与MATLAB生成动态库函数混编方法
2.2.1 使用MATLAB生成动态库的配置
首先安装matlab运行时,在matlab的command window中输入mcrinstaller即可找到MCR的位置,点击安装即可。
在VC++目录下包含目录增加:C:\Program Files\MATLAB\R2012b\extern\include,
C:\Program Files\MATLAB\R2012b\extern\include\win64
库目录增加:C:\Program Files\MATLAB\R2012b\extern\lib\win64\microsoft(如图2-6到2-8所示)
图2-6 使用MATLAB生成动态库配置-1
图2-7 使用MATLAB生成动态库配置-2
图2-8 使用MATLAB生成动态库配置-3
在链接器中输入添加附加依赖项mclmcrrt.lib mclmcr.lib Recon
预编译头中加入
#include ” mclmcrrt.h”
#include “mclc”
#include “Recon”头文件
然后初始化应用,初始化库函数(例如库文件名称为Restruction),代码如下:
If(!mclInitializeApplication(NULL,0))
{
AfxMessage(“Could not initialize the application!”);
}
If(!lRestructionInitialize())
{
AfxMessage(“Could not initialize the Restruction!”);
}
2.2.2 在没有安装MATLAB机器上的配置
由于MATLAB过于庞大,且安装费时,占用内存,所以一般不用在机器上安装整个MATLAB客户端,只需要安装MCR就能用VC调用MATLAB生成的动态库。安装方法见2.2.1。
在VC++目录下包含目录增加:
C:\Program Files\MATLAB\MATLAB Compiler Runtime\v80\extern\include
C:\Program Files\MATLAB\ MATLAB Compiler Runtime\v80\extern\include\win64
库目录增加:
C:\Program Files\MATLAB\ MATLAB Compiler Runtime\v80\\extern\lib\win64\microsoft
其他的配置见2.2.1。
2.2.3 VC+MATLAB混编举例
例1
void Function(IN BYTE* pHBlob,BYTE* pLBlob,OUT BYTE* pBlob)
{
int iWid=300;
int iHei=300;
//定义MATLAB函数要使用的变量
mwArray* mwpHBlob;
mwArray* mwpLBlob;
mwArray* mwpBlob;
//为变量分配空间
mwpHBlob=new mwArray(iWid,iHei,mxUINT8_CLASS,mxReal);
mwpLBlob=new mwArray(iWid,iHei,mxUINT8_CLASS,mxReal);
mwpBlob=new mwArray(iWid,iHei,mxUINT8_CLASS,mxReal);
//将VC输入变量的值传给MATLAB输入变量
mw(pHBlob,iWid*iHei);
mw(pLBlob,iWid*iHei);
//执行MATLAB函数,函数第一个参数为输出变量值的个数
Reconstrction(1, mwpBlob, mwpHBlob, mwpLBlob);
//将MATLAB输出变量值传递给VC函数输出变量值
mw(pHBlob,iWid*iHei);
//销毁内存
delete mwpHBlob;
delete mwpLBlob;
delete mwpBlob;
return;
}
例2
CString strFrontPath=CString(“F:\\正面训练数据路径\\”);
mwArray * G_MWTrainDataFrontPath;
mwArray * G_MWRefGridDataFront;
mwArray * G_MWSubFrontRefImg;
G_MWTrainDataFrontPath=new mwArray(strFrontPath);
const char* fields[]={"V","meanV"};
G_MWRefGridDataFront=new mwArray(10,20,2,fields);
G_MWSubFrontRefImg=new mwArray(1000,2000,mxUINT8_CLASS,mxREAL);
mwArray V1(30000,50,mxDOUBLE_CLASS);
mwArray meanV1(1,30000,mxDOUBLE_CLASS);
for (int i=1;i<=10;i++)
{
for (int j=1;j<=20;j++)
{
(*G_MWRefGridDataFront)(fields[0],i,j)=V1;
(*G_MWRefGridDataFront)(fields[1],i,j)=meanV1;
}
}
loadMat(2,*G_MWRefGridDataFront,*G_MWSubFrontRefImg,*G_MWTrainDataFrontPath);