VC与MEX文件示例二

一般情况下,我们都是在MATLAB命令行下编译MEX文件,所用命令为:

code.matlab
>>mex Filename.c

但因MEX文件是以C/C++语言为主编写的程序,只不不过在MEX文件中添加了接口函数mexFunction,且该函数可与C/C++函数相一致。因此,可在VisualC++的IDE环境中编译MEX文件。这种方法将极大地方便编程者利用VisualC++ ClassWizard创建类和维护类,并利用VisualC++的项目管理进行项目管理。由于此种方法编写的MEX文件是在VisualC++的IDE环境中编译,因此,其调试方法与一般VC工程基本一致。

本节以“MyDLL”工程为例,阐述在VisualC++的IDE环境中编写和编译MATLAB MEX文件。

(1)修改mex.h

该文件在%MATLAB7%extern\include目录中,打开该文件,找到mexFunction函数申明,利用VC中的关键字“__declspec(dllexport)”,申明该函数为导出函数,并将文件另存为“mex_VC.h”。

code.vc
/////////////////////原 MEX.h文件
void mexFunction(
    int           nlhs,           /* number of expected outputs */
    mxArray       *plhs[],        /* array of pointers to output arguments */
    int           nrhs,           /* number of inputs */
    const mxArray *prhs[]         /* array of pointers to input arguments */
);
/////////////////////修改并另存为mex_VC.h
__declspec(dllexport)void mexFunction(
    int           nlhs,           /* number of expected outputs */
    mxArray       *plhs[],        /* array of pointers to output arguments */
    int           nrhs,           /* number of inputs */
    const mxArray *prhs[]         /* array of pointers to input arguments */
);

(2)创建MFC AppWizard(dll)工程MyDll

运行VisualC++并单击File->New,打开Project对话框来创建各种VC工程,选取MFC Appwizard(dll)(图1-1,其它程序基本相同)。在loctation编辑框中输入欲创建工程的保存路径,在Project name编辑框中输入工程名如“MyDll”,单击OK进入下一步工程设置对话框,选中Regular DLL with MFC Statically Linked,单击Finish完成MyDll工程创建。

Document Image

图1-1 MyDll工程创建

(3)设置系统选项

•设定头文件和库文件路径

菜单Tools->Options->Directories

Include files:添加%MATLAB7%extern\include

Include files:添加%MICROSOFT VISUALSTUDIO%VC98\MFC\SRC

Library files:添加%MATLAB7%extern\include

•设置编译连接选项

菜单Project->Settings

C/C++->Preprocessor definitions: 添加MATLAB_MEX_FILE

Link->Object/Library modules: 添加libmat.lib libmex.lib libmx.lib

General->Microsoft Foundation Classes: Use MFC in a Static Library

(4)编写DLL主程序

•在MyDll.h中添加头文件:

#include "mex_vc.h"

•在MyDll.cpp中添加头文件:

#include "stdafx.h"

•编写mexFunction函数

在MyDll.cpp文件最后中找到:CMyDllApp theApp;

在其后编写用户C函数和mexFuntion接口函数如下:

code.vc
/////////////////////////////////用户C函数,**注:不在MyDll.h中进行函数申明
double OutPut(int n, double *rP)
{
 int i;  double *sum,sum0;
 FILE *fp1;

sum=new double[1];//////////////////内存在管理机制为Cpp机制
if((fp1=fopen("OutPut1.txt","w"))==NULL){printf(" Can't open OutPutfile\n");exit(0);}
*sum=0.0;
fprintf(fp1,"Input %d Data is:",n);
for(i=0;i<n;i++){*sum=*sum+rP[i];fprintf(fp1," %7.2lf ",rP[i]);}
fprintf(fp1,"\nsum= %7.2lf \n",*sum);
fclose(fp1);
sum0=*sum;
delete sum;//////////内存在管理机制为Cpp机制
return sum0; /////// Cpp程序返回计算值
}
//////////////////////////////接口函数,**注:不在MyDll.h中进行函数申明
void mexFunction(
int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]
)///////////////////////////////////////////////////注:mexFunction要与mex_vc.h中一致,分行写
{int i;
double *rP,*lP,sum;
mxArray *lP0;
////////////////// 由 prhs[] 中取得MATLAB输入数据
rP=new double[nrhs]; //////////内存在管理机制为Cpp机制
for(i=0;i<nrhs;i++)rP[i]=mxGetScalar(prhs[i]);
/////////////////  调用Cpp程序
sum=OutPut(nrhs,rP);
////////////////   进行数据类型转换,并存入 plhs[] 返回MATLAB
nlhs=nrhs;
plhs[0]=mxCreateDoubleMATrix(1,nlhs,mxREAL);
lP0=mxCreateDoubleMATrix(1,nlhs,mxREAL);
lP= new double[nlhs];
for(i=0;i<nlhs;i++)lP[i]=i*sum;
for(i=0;i<nlhs;i++)*(mxGetPr(lP0)+i)=*(lP+i);
plhs[0]=mxDuplicateArray(lP0); //使用内存数据拷贝函数mxDuplicateArray()
mxDestroyArray(lP0); ///////////内存在管理机制为MATLAB机制
delete rP;
delete lP;
}
////////////////////////结束

在VisualC++中编译得得动态链接子程序MyDll.dll,并在MATLAB命令行中调用。

code.matlab
>> clear all
>> Mydll(1,2,4,5,6,7)
ans =
     0    25    50    75   100   125

同时,由于用户Cpp程序中执行了文件输出,在当前目录下生成“OutPut1.txt”文件,输出结果为:

code.matlab
Input 6 Data is:    1.00     2.00     4.00     1.00     6.00     7.00
sum=   21.00