matlab和VC混合编程综述.docx
《matlab和VC混合编程综述.docx》由会员分享,可在线阅读,更多相关《matlab和VC混合编程综述.docx(18页珍藏版)》请在冰豆网上搜索。
matlab和VC混合编程综述
程序中使用MATLAB编译产生的DLL(VS2005,MATLAB7.5,mwArray)
2007-12-1614:
52:
39| 分类:
MatLab/Maple/Mat|字号 订阅
from:
程序中使用MATLAB编译产生的DLL(VS2005,MATLAB7.5,mwArray)
最近有几个帖子都在讨论有关在C++程序中使用MATLAB编译产生的动态链接库DLL。
本来想用原来帖子中给出的m代码作为例子,无奈那段代码其实无法执行。
为了避免分散注意力,也为了更好地讨论问题,于是决定还是另外新开一个主题,以简单的例子,和大家一起讨论如何在C++程序中使用matlab编译产生的DLL。
同时MATLAB最新版本R2007b刚刚发布不久,其中包含编译器4.7版,有了一些新的特性,于是也借这个例子来验证一下相关的技术有没有发生大的变化。
最近讨论的问题是关于在C++程序中调用MATLAB编译产生的动态链接库。
具体的问题是在调用DLL中函数时传递参数。
我们知道,MATLAB可以把m代码编译成两种DLL,分别是C语言接口和C++语言接口的DLL。
论坛上的问题是关于调用C++接口的DLL中的函数,所以这里我们就以这种DLL为例来介绍。
在C++接口的DLL中,函数的输入、输出参数都是mwArray对象。
所以问题归结为如何在C++程序中使用mwArray。
这个问题本来可以只用一个简单的C++程序来练习,而不需要MATLAB编译的DLL。
不过为了模拟实际情况,选择以一个更为接近实际的m代码作为例子。
在这个例子中,输入输出都是矩阵,至于标量,它也是一个一行、一列的矩阵。
实验环境:
Windows2003StdServerwithSP2(En),MATLABR2007b,VisualStudio2005。
MATLAB安装路径:
h:
MATLABR2007b。
实验内容:
把一个简单的m代码编译成C++接口的DLL,然后在C++程序中调用。
为了简单起见,这里的C++程序是一个Win32Console程序,而不是Windows图形界面的程序,不过不妨碍我们的讨论。
下面是这个例子用到的m代码。
它定义了一个名为myadd2的函数:
[Copytoclipboard] [-]
CODE:
function[y,z]=myadd2(a,b)
%dummyfunction,justtodemonstratetheidea
y=a+b;
z=a+2*b;
end
首先把这个函数编译成C++接口的DLL。
为此,我们需要先设置MATLAB编译器。
具体做法是在MATLAB命令行执行“mbuild-setup”。
然后用下面这行命令把myadd2函数编译成一个C++接口的DLL:
[Copytoclipboard] [-]
CODE:
mcc-Wcpplib:
libmyadd2-Tlink:
libmyadd2
结果,我们将会得到包含libmyadd2.dll,libmyadd2.ctf,libmyadd2.h,libmyadd2.lib等在内的一些文件。
接下来我们只需要这四个文件。
请注意:
在MATLABR2007b之前,这些文件都会在和编译
的m代码所在的目录中,而在MATLABR2007b,缺省情况下这些文件会在DocumentsandSettings中用户的MyDocuments目录中。
此时,打开libmyadd2.h看看,在文件的最下面我们可以发现C++接口的函数定义。
仔细观察过后,我们可以发现,这个接口函数的参数是按照这样的顺序定义的:
输出参数的个数、输出参数、以及输入参数。
然后在VS2005中创建一个Win32Console的VC++工程,我在测试时取名为testmyadd2_r2007b。
把以上四个文件拷贝到VC++工程的源代码所在目录。
接下来设置VC++,让它能找到MATLAB接口函数的定义及连接库函数。
可以有两种设置方式:
一种是改VS2005中关于VC++的设置,这样的好处是每个新的工程都能自动获得这个设定;而另一种是只改当前工程的设置,也就是设置只对该工程有效。
这里用后一种方式。
在VS2005中打开工程testmyadd2_r2007b,选择菜单“Project-->Properties,在出来的对话框上,把MATLAB提供的include路径加到VC++的头文件搜索路径。
如图所示:
然后把相应的lib所在目录加到linker的额外搜索路径上。
如图所示:
接下来,告诉VC++,我们的这个程序需要连接到另外两个额外的库函数:
libmyadd2.lib和mclmcrrt.lib。
中间用空格隔开。
如图所示:
最后则是程序代码。
这个程序只有一个main函数,其完整代码附在下面给大家参考。
欢迎大家拍砖。
谢谢!
CODE:
#include"stdafx.h"
#include
#include"mclmcr.h"
#include"mclcppclass.h"
#include"libmyadd2.h"
int_tmain(intargc,_TCHAR*argv[])
{
std:
:
cout<<"Helloworld!
"<:
endl;
/*InitializetheMCR*/
if(!
mclInitializeApplication(NULL,0))
{
std:
:
cout<<"Couldnotinitializetheapplication!
"<:
endl;
return-1;
}
//initializelib
if(!
libmyadd2Initialize())
{
std:
:
cout<<"Couldnotinitializelibmyadd2!
"<:
endl;
return-1;
}
try
{
//declareandinitializea
mwArraya(2,2, mxDOUBLE_CLASS);
double*aData;
aData=newdouble[4];
inti;
for(i=0;i<4;++i)
{
aData[i]=1.0*i;
}
//printoutput
std:
:
cout<<"a="<:
endl;
std:
:
cout<:
endl;
std:
:
cout<:
endl;
a.SetData(aData,4);
//declareandinitializeb
mwArrayb(2,2, mxDOUBLE_CLASS);
b(1,1)=11.;
b(1,2)=12.;
b(2,1)=21.;
b(2,2)=22.;
mwArrayy(2,2, mxDOUBLE_CLASS);
mwArrayz(2,2, mxDOUBLE_CLASS);
//callthefunction
myadd2(2,y,z,a,b);
//copydatafrommwArraytoC++objects
//allocateoutputs
double*yData,*zData;
yData=newdouble[4];
if(yData==NULL)
{
std:
:
cout<<"FailedtoallocatememoryforyData!
"<:
endl;
return-1;
}
zData=newdouble[4];
if(zData==NULL)
{
std:
:
cout<<"FailedtoallocatememoryforzData!
"<:
endl;
return-1;
}
//copydatafrommwArraytoC++
y.GetData(yData,4);
z.GetData(zData,4);
//printoutput
std:
:
cout<<"y="<:
endl;
std:
:
cout<:
endl;
std:
:
cout<:
endl;
std:
:
cout<<"z="<:
endl;
std:
:
cout<:
endl;
std:
:
cout<:
endl;
//deallocatememory
delete[]aData;
delete[]zData;
delete[]yData;
}
catch(constmwException&e)
{
std:
:
cerr<:
endl;
}
//terminatethelib
libmyadd2Terminate();
//terminateMCR
mclTerminateApplication();
return0;
}
2007-10-623:
18
实验的结果表明,在C++程序中使用MATLAB编译产生的C++接口DLL非常容易。
mwArray也很容易使用。
另外,最新的MATLABR2007b中关于这部分并没有什么大的变化。
这个练习适合MATLAB7.0以后直到MATLABR2007b的所有版本。
ask:
就我个人6.5混编的经验,我很少弄DLL,直接编译M文件为cpp,h文件即可,VC工程中引用,按.h文件格式调用即可。
这样混编基本没有任何难度,将MATLAB程序看成MFC一个类即可,看看extern里面
相关头文件的定义,跟看MSDN一样。
抛开mclTerminateApplication();这些,这应该是一个通用的办法
手头只有6.5,不知道7.5还能生成cpp么?
answer:
从matlab7.0开始,其编译器的功能就和以前版本不一样了。
它不再把m代码翻译成C/C++源代码,而是对m代码作个简单的wrapper,通常以动态链接库的形式提供给用户以方便用户在其他的程序中使用。
所以,在matlab7.x,编译m代码不能得到以前那种意义的C/C++源程序。
不过,仅从软件开发的角度来看,我觉得用DLL来打包更为方便。
如果m函数的接口不变,那么每次改变m代码后,我们只需重新编译m代码,获得新的DLL及CTF,而不需要重新编译VC客户程序。
这在开发大型软件时有很大的优越性。
多谢taohe的文章,我想问一下,ctf文件是干嘛用的,谢谢,记得matlab6.5版里面编译为DLL时没这个东西啊。
这是matlab7.0以后matlab编译器的新特性。
它和旧版技术不兼容。
ctf其实就是一个zip文件,其中包含加密或者说编码过的一些m代码。
其中有你自己的代码,以及matlab编译器通过分析你的代码根据依赖关系找到的其他一些m代码
matlab7.0.1与vc6.0混合编程之DLL
2009-10-2420:
35:
53| 分类:
默认分类|字号 订阅
matlab7.0.1与vc6.0混合编程成功
matlab 2008-01-0518:
11 阅读600 评论0
字号:
大大 中中 小小
混合编程其实不难,关键是没有一个规范的,真正可以解决设置过程中出现的小问题的方法。
我在设置的过程中,遇到了不少问题,花了多半天的时间,终于解决了,顺利地在vc中调用matlab生成的dll文件中的函数,并返回一个值,探出对话框,显示正确。
这种混合编程的方式不能脱离matlab环境,如果需要发布独立的应用程序,需要安装MCR。
下面分步骤地讲一下混合编程的设置及其原因:
1 matlab方面的操作
首先先写一个算阶乘的函数,存成test1.m文件,该文件的内容是:
functiony=test1(n)
y=1;
fori=1:
n
y=y*i;
end
现在有了文件,下一步我们要设置好系统,设置好matlab,然后再把该文件编译成dll文件。
1、在环境变量(我的电脑右键-高级)path中加入\bin\win32;
2、添加环境变量matlab值设为即matlab7.1的安装路径;
3、配置mbuild使用的C/C++编译器;
在Matlab命令窗口中输入:
mbuild-setup
按照提示选择VC6.0的编译器,完成后在Matlab命令窗口中输入:
mex-setup
同样选择VC6.0的编译器,就完成编译器的安装和配置。
接下来我们要把.m文件存储的程序编译成dll文件,在matlab命令窗口中输入:
mcc-Wlib:
test1-Tlink:
libtest1.m
这个需要等一小段时间,最终,在当前目录下生成了
到此,在操作系统和matlab这一方面的工作就做完了
2vc++6.0中的操作
在vc中建立一个MFCAppWizard[exe]基本对话框工程,名字叫做test1app.
1 )在 VC 中创建一个 MFC 工程(本人创建的为基于对话框的),环境设置根据如下帖子
:
怎样设置 Visual Studio 与 Matlb Complier 4.0 一起工作 中的指导进行。
在
本例子中,只需要在 VC 中进行如下步骤:
A. Tools->Options->Directories->Show directories for :
Include files->7root> \Extern\Include ;
B. Tools->Options->Directories->Show directories for :
Library files->7root> \Extern\Lib\Win32\Microsoft\msvc60 ;
C. Project->Setting->C/C++->Category :
Code Generation->Use run-time library
:
Debug Multithread DLL ;
D. Project->Setting->Link->Category :
Input->Object/library modules :
test1.libmclmcr.liblibmx.liblibmat.liblibeng.lib
2 )拷贝 MATLAB 当前目录下刚才用 mcc 生成的 test1.h , test1.dll , test1.lib ,以及 test1.ctf 文件到 VC 当前工程目录下,并用 Project->Add to Project->Files… 将 test1.h 加入到当前工程中。
3 )在当前工程的对话框的头文件和cpp中加入 #include "test1.h" 与 #include "mclmcr.h" ;
工程设置到此就结束了,下面开始写代码:
首先需要在对话框的初始化程序BOOLCTest1appDlg:
:
OnInitDialog()内写
if(!
mclInitializeApplication(NULL,0))//matlab环境初始化
{
AfxMessageBox("Couldnotinitializetheapplication.");
exit
(1);
}
/*Callthelibraryintializationroutineandmakesurethatthe
*librarywasinitializedproperly.*/
if(!
test1Initialize()) //test1Initialize是test1.h中定义的test1函数的初始化函数
{
AfxMessageBox("Couldnotinitializethelibrary.");
exit
(1);
}
在对话框的确定按钮的消息响应函数内,调用dll中的阶乘函数,
voidCTest1appDlg:
:
OnOK()
{
//TODO:
Addextravalidationhere
//此处为dll中的函数准备好参数,然后调用
double n=4;
mxArray *t; //经过matlab编译完的dll中的函数只能识别mxArray 类型的参数,所以我们在vc中定义的数值
//都需要转换成该种格式
t=mxCreateDoubleMatrix(1,1,mxREAL);//该函数中的参数1,1定义了t这个矩阵的大小
memcpy(mxGetPr(t),&n,sizeof(double));//给t赋值为4
mxArray*y; //准备一个接收返回值的变量
y=mxCreateDoubleMatrix(1,1,mxREAL);
mlfTest1(1,&y,t); //运行该函数,进行阶乘计算,4的
doubler1=0; //vc中的接收返回值的函数
memcpy(&r1,mxGetPr(y),sizeof(double));
mxDestroyArray(t);//销毁废弃内存
test1Terminate();//中止调用
CStringshowrslt;
showrslt.Format("%f",r1);
AfxMessageBox(showrslt);//显示阶乘计算的结果
CDialog:
:
OnOK();
}
mxDestroyArray(t);//销毁废弃内存
test1Terminate();//中止调用
CStringshowrslt;
showrslt.Format("%f",r1);
AfxMessageBox(showrslt);//显示阶乘计算的结果
CDialog:
:
OnOK();
}
VC与Matlab混合编程(在VC中调用DLL)的实现
本人所用系统为windows7旗舰版,MATLAB为R2008a和MicrosoftVisualC++6.0编程环境。
一、 MATLAB编译环境的设置
为了能够使用MATLAB的Complier将*.m函数文件编译为动态链接库DLL,必须对MATLAB的环境做出相应的设置。
具体做法如下:
在MATLAB的CommandWindow下输入命令 mbuild–setup,并根据MATLAB的提示选择合适的编译器,笔者使用的是MicrosoftVisualC++6.0,进行对C++连接环境的设置。
过程如下:
>>mbuild-setup
PleasechooseyourcompilerforbuildingstandaloneMATLABapplications:
Wouldyoulikembuildtolocateinstalledcompilers[y]/n?
y
Selectacompiler:
[1]Lcc-win32C2.4.1inD:
/PROGRA~1/MATLAB/R2008a/sys/lcc
[2]MicrosoftVisualC++2005ind:
/ProgramFiles/MicrosoftVisualStudio8
[3]MicrosoftVisualC++6.0inD:
/ProgramFiles/MicrosoftVisualStudio
[0]None
Compiler:
3
Pleaseverifyyourchoices:
Compiler:
MicrosoftVisualC++6.0
Location:
D:
/ProgramFiles/MicrosoftVisualStudio
Arethesecorrect[y]/n?
y
Tryingtoupdateoptionsfile:
C:
/DocumentsandSettings/hk/ApplicationData/MathWorks/MATLAB/R2008a
/compopts.bat
Fromtemplate:
D:
/PROGRA~1/MATLAB/R2