Matlab75a函数转换成VC++60动态链接库修改.docx
《Matlab75a函数转换成VC++60动态链接库修改.docx》由会员分享,可在线阅读,更多相关《Matlab75a函数转换成VC++60动态链接库修改.docx(16页珍藏版)》请在冰点文库上搜索。
Matlab75a函数转换成VC++60动态链接库修改
Matlab7.0函数转换成VC++6.0动态链接库[转+修改]
1、mcc4.0编译环境设置
在桌面上右键单击“我的电脑”图标出现以下菜单
单击“属性”菜单项,出现“系统特性”对话框,单击“高级”选项卡,如下图所示
在上图中,单击“环境变量”按钮,出现“环境变量”对话框,添加系统变量matlab值为C:
\MATLAB7即matlab7.0的安装路径,如下图所示
在环境变量path中加入C:
\MATLAB7\bin\win32,如下图所示
按“确定”完成设置后,重启计算机或注销当前用户,即可应用新设置。
2、Matlab7.0编译器设置
(1)mex命令设置
(a)运行Matlab,在Matlab的命令窗口(CommandWindow)键入“mex-setup”命令后,按回车键,安装Matlab编译器;
(b)命令窗口出现如下提示:
Pleasechooseyourcompilerforbuildingexternalinterface(MEX)files:
Wouldyoulikemextolocateinstalledcompilers[y]/n?
此时键入”y”,按回车;
(c)命令窗口出现如下提示:
Pleasechooseyourcompilerforbuildingexternalinterface(MEX)files:
Wouldyoulikemextolocateinstalledcompilers[y]/n?
y
Selectacompiler:
[1]DigitalVisualFortranversion6.0inC:
\ProgramFiles\MicrosoftVisualStudio
[2]LccCversion2.4inC:
\MATLAB6P5\sys\lcc
[3]MicrosoftVisualC/C++version6.0inC:
\ProgramFiles\MicrosoftVisualStudio
[0]None
此时键入”3”,按回车;选择MicrosoftVisualC++6.0的编译器
(d)命令窗口出现如下提示:
Pleaseverifyyourchoices:
Compiler:
MicrosoftVisualC/C++6.0
Location:
C:
\ProgramFiles\MicrosoftVisualStudio
Arethesecorrect?
([y]/n):
此时键入”y”,按回车;确认选择MicrosoftVisualC++6.0的编译器
(2)mbuild命令设置
(a)运行Matlab,在Matlab的命令窗口(CommandWindow)键入“mbuild-setup”命令后,按回车键,安装Matlab编译器;
(b)命令窗口出现如下提示:
PleasechooseyourcompilerforbuildingstandaloneMATLABapplications:
Wouldyoulikembuildtolocateinstalledcompilers[y]/n?
此时键入”y”,按回车;
(c)命令窗口出现如下提示:
[1]LccCversion2.4inC:
\MATLAB6P5\sys\lcc
[2]MicrosoftVisualC/C++version6.0inC:
\ProgramFiles\MicrosoftVisualStudio
[0]None
此时键入”2”,按回车;选择MicrosoftVisualC++6.0的编译器
(d)命令窗口出现如下提示:
Pleaseverifyyourchoices:
Compiler:
MicrosoftVisualC/C++6.0
Location:
C:
\ProgramFiles\MicrosoftVisualStudio
Arethesecorrect?
([y]/n):
此时键入”y”,按回车,确认选择MicrosoftVisualC++6.0的编译器,编译器设置完成。
3、编写Matlab函数
函数文件sum_prod.m,内容如下:
function[sum,prod]=sum_prod(p1,p2)
sum=p1+p2;%p1与p2的和
prod=p1.*p2;%p1与p2的点乘
该函数完成的是矩阵的求和与点乘的功能,下面将介绍把该代码转换成VC++环境可用的代码的方法。
4、将Matlab函数转成DLL函数
在Matlab7.0的CommandWindow下输入命令:
命令1:
mcc-Wlib:
libsum_prod-Tlink:
libsum_prod.m
或
命令2:
mcc-Wcpplib:
libsum_prod-Tlink:
libsum_prod.m
生成动态链接库DLL,编译完成后,Matlab生成一些文件,其中
libsum_prod.ctf
libsum_prod.dll
libsum_prod.h
libsum_prod.lib
这些文件是我们后面需要用到的。
特别注意:
命令1生成的DLL函数接口的数据类型是mxArray,命令2生成的DLL函数接口的数据类型是mwArray。
5、VC++6.0工程的创建与设置
(1)建立一个名为Test的C++控制台工程,在工程中添加一个名为Test.cpp文件
(2)对VC++6.0,进行以下设置
单击菜单Tools,出现如下菜单
单击Options…菜单项,出现Options对话框,选择Directories标签,在includefiles里面加入:
C:
\MATLAB7\EXTERN\INCLUDE
如下图所示
在Libraryfiles里面加入:
C:
\MATLAB7\EXTERN\LIB\WIN32\MICROSOFT\MSVC60
如下图所
(3)对该工程,进行以下设置
单击菜单Project,出现如下菜单
单击Setting…菜单项,出现ProjectSetting对话框,选择Link标签,在Object/librarymodules:
下面的文本框内容的后面加入mclmcrrt.liblibsum_prod.lib,如下图所示
6、代码编辑及DLL调用
(1)将前面生成的四个文件:
libsum_prod.ctf
libsum_prod.dll
libsum_prod.h
libsum_prod.lib
复制到VC工程所在目录。
(2)在VC++6.0环境中,单击菜单Project,选择AddtoProject菜单项,再单击Files…子菜单项,出现如下图对话框,
将libsum_prod.h加入到当前工程中。
3)当用命令1生成的DLL函数时,在工程文件Test.cpp中添加以下代码:
#include"iostream.h"//输入输出头文件
#include"mclmcr.h"//mxArray类型声明
#include"libsum_prod.h"//DLL头文件
voiddisplay(constmxArray*in,constchar*name);
intmain()
{
//初始化程序
if(!
mclInitializeApplication(NULL,0))
{
fprintf(stderr,"Couldnotinitializetheapplication.\n");
exit
(1);
}
//初始化库
if(!
libsum_prodInitialize())
{
fprintf(stderr,"Couldnotinitializethelibrary.\n");
exit
(1);
}
//声明DLL函数输入输出mxArray对象
mxArray*X,*Y;
mxArray*SUM=NULL,*PROD=NULL;
//给输入mxArray对象分配内存
X=mxCreateDoubleMatrix(2,3,mxREAL);
Y=mxCreateDoubleMatrix(2,3,mxREAL);
doublex[]={1,2,3,4,5,6};
doubley[]={7,8,9,10,11,12};
//给输入mxArray对象赋值
memcpy(mxGetPr(X),x,6*sizeof(double));
memcpy(mxGetPr(Y),y,6*sizeof(double));
//调用DLL函数,注意输入与输出的接口是不同的
mlfSum_prod(2,&SUM,&PROD,X,Y);
//显示mxArray对象
display(SUM,"SUM");
display(PROD,"PROD");
//释放输入输出mxArray对象所占用的内存
//注意输出对象的内存是在调用DLL函数过程中分配的
mxDestroyArray(X);
mxDestroyArray(Y);
mxDestroyArray(SUM);
mxDestroyArray(PROD);
//关闭库和程序
libsum_prodTerminate();
mclTerminateApplication();
return0;
}
//显示矩阵函数
voiddisplay(constmxArray*in,constchar*name)
{
inti,j,r,c;
double*data;
data=mxGetPr(in);
r=mxGetM(in);
c=mxGetN(in);
printf("%s=\n",name);
for(i=0;i
{
printf("\t");
for(j=0;j
printf("%4.2f\t",data[j*r+i]);
printf("\n");
}
printf("\n");
}
该C++程序运算结果如下图所示
(4)当用命令2生成的DLL函数时,在工程文件Test.cpp中添加以下代码:
#include"iostream.h"//输入输出头文件
#include"mclmcr.h"//mwArray类型声明
#include"libsum_prod.h"//DLL头文件
voiddisplay(constdouble*data,constintr,constintc,constchar*name);
intmain()
{
//初始化程序
if(!
mclInitializeApplication(NULL,0))
{
fprintf(stderr,"Couldnotinitializetheapplication.\n");
exit
(1);
}
//初始化库
if(!
libsum_prodInitialize())
{
fprintf(stderr,"Couldnotinitializethelibrary.\n");
exit
(1);
}
//声明DLL函数输入输出mwArray对象
mwArrayX(2,3,mxDOUBLE_CLASS);
mwArrayY(2,3,mxDOUBLE_CLASS);
mwArraySUM,PROD;
doublex[]={1,2,3,4,5,6};
doubley[]={7,8,9,10,11,12};
double*sum,*prod;
sum=newdouble[6];
prod=newdouble[6];
//给输入mwArray对象赋值
X.SetData(x,6);
Y.SetData(y,6);
//调用DLL函数
sum_prod(2,SUM,PROD,X,Y);
//取出输出数据
SUM.GetData(sum,6);
PROD.GetData(prod,6);
//显示mwArray对象
//std:
:
cout<<"SUM="<:
endl<:
endl;;
//std:
:
cout<<"PROD="<:
endl<:
endl;;
display(sum,2,3,"SUM");
display(prod,2,3,"PROD");
deletesum;
deleteprod;
//关闭库和程序
libsum_prodTerminate();
mclTerminateApplication();
return0;
}
//显示矩阵函数
voiddisplay(constdouble*data,constintr,constintc,constchar*name)
{
inti,j;
printf("%s=\n",name);
for(i=0;i{
printf("\t");
for(j=0;jprintf("%4.2f\t",data[j*r+i]);
printf("\n");
}
printf("\n");
}
该C++程序运算结果如下图所
特别说明:
在C\C++环境中二维数组是“行向量”,如果将下面定义的变量x看成二维数组的话
doublex[]={1,2,3,4,5,6};
那么x应该是
的矩阵,即
x=[1,2,3;
4,5,6];
但是,如果将数组首地址x初始化mxArray和mwArray类时,数组x在mxArray和mwArray类中是按“列向量”的形式排列的,即
X=[1,3,5;
2,4,6];
同理,这里
Y=[7,9,11;
8,10,12];
因此才能得到上图的结果
mwArray和mxArray有什么区别?
首先,mxArray是MatlabC函数库的结构体,而mwArray是MatlabC++函数库中对mxArray的包装类。
其次,二者的内存管理方式不同。
mxArray的内存管理方式比较松散,由于是C函数库,没有数据封装,必须对临时阵列和约束阵列的概念极为明确,并且须小心地防止内存泄漏(要多写好多代码)。
尽管有自动内存管理机制(mlfEnterNewContext,mlfReleasePreviousContext),仍然要处处调用mlfAssign,麻烦得很。
然而mwArray就好的多,一切交给C++对象去搞定,你只要放心地用就可以了。
不过MatlabC++函数库为了防止频繁内存分配和释放重写了内存分配和释放等函数。
你会发现对于mwArraya,b;a=b;实际上并没有生成两个相同数据块,只是指针,只有发成数据改变时才copy完整数据。
再次,这两个东西各自有一套与之相对应的函数。
函数的返回值类型不同,需要多加注意。
最后,用的时候mxArray要使用指针,而mwArray直接当类对象使。
如果你不是Hardcore级的牛人或具有Hardcore倾向的潜牛人,我强烈建议你使用后者!
举一个简单的例子:
如果你需要计算c=a+b那么两者的区别是这样的:
mxArray:
voidfun(){
……
doubled_a=1,d_b=2;
mxArray*a,*b,*c;
mlfEnterNewContext(0,0);
mlfAssign(&a,mlfScalar(d_a));
mlfAssign(&b,mlfScalar(d_b));
mlfAssign(&c,mlfPlus(a,b));
……
mlfReleasePreviousContext(0,0);
mxDestroyArray(a);
mxDestroyArray(b);
mxDestroyArray(c);
}
mwArray:
voidfun(){
……
mwArraya,b,c;
a=1;
b=2;
c=a+b;
……
}
------------------------------------------------------------------
另外一个说法:
声明:
mxArray:
mxArray*a;
mwArray
mwArraya;
销毁
mxArray
mxDestroyArraya;
mwArray
mwArray类的析构函数自动销毁对象
变量传递
mxArray
memcpy(dest_ptr,source_ptr,MAX_SIZE);
mwArray
mwArrayin1(3,3,mxDOUBLE_CLASS,mxREAL);mwArrayin2(3,3,mxDOUBLE_CLASS,mxREAL);in1.SetData(data,9);in2.SetData(data,9);
比较而言,
1。
mwArray的声明更简洁,不用考虑指针
2。
mwArray不用手动释放内存
建议参考mwArray的帮助信息,推荐使用mwArray:
:
setData函数来把C++数组数据传递给mwArray对象,从而传递给调用函数。
下面是帮助中给出的一段示例代码:
#include"mclcppclass.h"
doublerdata[4]={1.0,2.0,3.0,4.0};
doubledata_copy[4];
mwArraya(2,2,mxDOUBLE_CLASS);
a.SetData(rdata,4);
a.GetData(data_copy,4);
最后,建议大家分阶段调试代码,只是弄清楚错误出在那个阶段:
比如是否已经正确地从用户界面拿到了数据,是否已经正确的创建了mwArray对象,等等。
简单的“运行时间错误”可能和所有这些步骤都有关。
另外,请不要指明让某某人进来看贴,这对于问题没有丝毫帮助,反而导致提问者更晚获得帮助,
我还是怀疑程序在别的地方有问题。
创建和传递mwArray并没有什么特别的。
下面贴上书中第七章例子mccmfc02中的代码,其中创建一个mwArray对象,对应于两个元素的一维数组,然后传递给matlab编译后的函数。
希望能有所帮助。
voidCmccmfc02Dlg:
:
OnBnClickedButtonTest()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
doublefigsize[]={0.0,0.0};
//Getclientareasize
CRectclient_rect;
GetClientRect(&client_rect);
figsize[0]=client_rect.Width();
figsize[1]=client_rect.Height();
//constructaninstanceofmwArrayofthefiguresize
mwArraymwFigSize(2,1,mxDOUBLE_CLASS,mxREAL);
mwFigSize.SetData(figsize,2);
//callthefunction
testcopyfigure(mwFigSize);
//pastethefigurefromtheclipboardtotheapplication
myFig.PasteFigure();
}
————————————————————————————————————————
不好意思,有点事情没能及时来看贴,请见谅。
下面是m文件
functionPcc(N,d,tar,S,null);
%N=30;
tar1=tar*pi/180;
%d=0.5;
Dx=[-(N-1)/2:
1:
(N-1)/2]*d;
u=-90:
0.1:
90;
u1=u*pi/180;
ui=null;
%ui=[40.5,39.5,39,-39,-38.5,-38];
%ui=[30,31];
nulls=ui*pi/180;
v=exp(j*2*pi*Dx.'*sin(u1));
vs=exp(j*2*pi*Dx.'*sin(tar1));
C=[exp(j*2*pi*Dx.'*sin(nulls))];
Wd=tay(30,S);
Pc=C*inv(C'*C)*C';
Wo=((Wd.*vs)'*(eye(Nx)-Pc))';
b=Wo'*v;
bdb=20*log10(abs(b)/max(abs(b)));
figure('visible','off');
%上句以及最后的两句是引用mcctest02中的,不知这样使用是否有误。
plot(u,bdb);
axis([-9090-12010]);
ylabel('B(dB)')
xlabel('\itu')
gridon
zoomon
print-dmeta
close(gcf)
下面是c++中调用的程序:
UpdateData(true);
doublex1=m_Num;
doublex2=m_wavelength;
doublex3=m_point;
doublex4=m_window;
doublex5[]={m_null1,m_