写在前面——这个是为了我个人便于查询而把我在网上搜到的一些关于vc中调用MATLAB函数的文章放到一起,后面贴有原文链接(有的也是转的)。第一个是MATLAB engine的,第二个是MATLAB+vc6产生DLL,第三个是MATLAB+vs2005也是产生DLL。 【转】 vc调用matlab函数 Matlab 是由Math Works 公司于1984 年推出的数值计算及图形处理软件,可以实现数值分析、优化、统计、偏微分方程数值解、自动控制、信号处理、图像处理等若干领域的计算和图形显示功能。其中,控制系统工具箱的集成为设计和分析各种复杂的控制系统提供了有效的方法和途径。 但是,由于Matlab开发平台的局限性,在其上面开发的程序不能脱离Matlab运行环境,因而在处理一些实际应用问题时显得灵活性不足,而VC++则在一定程度上能够弥补这一漏洞,因此,现将二者结合共用,各献其长,可以为科研工作和工程开发提供了更为强大的技术支持。 1、Matlab与VC混合编程的实现方法 Matlab作为控制系统设计的一种通用工具,它可以和VC方便的进行连接。一般而言,Matlab与VC混合编程的实现方法主要有以下三种方法:(1)通过引擎(Engine),采用客户机服务器的计算模式,通过Window的ActiveX通道和Matlab进行连接。具体应用时,往往在VC中设计程序框架,以编译的程序作为前端客户机;通过调用Matlab引擎在后台实现与服务器的连接,实现动态通信(2)应用Matlab数学函数库,Matlab中包含了内容丰富的函数库,而且还提供了与VC的数学函数接口,用户可以方便的在VC的IDE(集成开发环境)中调用。(3)通过DLL实现VC与Matlab的混合编程。DLL是一个可执行的二进制文件。把很多通用的功能放在DLL中,可以供多个应用程序调用,这样可以很好的减少外部存储空间的占有量,并实现代码的共享[2]。在上述三种方法中,第一种方法对调用Matlab的工具箱很实用,所有在进行控制系统的设计和分析时,一般都是通过调用Matlab引擎(Engine)来实现的。本文主要介绍采用通过引擎(Engine)来实现VC与Matlab的混合编程。 2、MATLAB引擎简介 Matlab引擎是Matlab提供的一系列程序的结合,它允许用户在自己的应用程序中对Matlab进行调用,将Matlab作为一个操作引擎使用,使其在后台运行。一般Matlab 引擎采用客户机/ 服务器(Client/ Sever) 计算方式,就是一种把应用处理负载分布到客户机和服务器上的一种计算模式,客户机和服务器既可以是存在于同一台计算机,也可以通过网络来实现信息共享。一般情况下,客户机是运行前端软件的PC机,并且知道如何与服务器通信,服务器与此相对应,是接收请求信息,并采取相应行的机器。由于客户机和服务器共同承担处理负载,使系统总体性能大为提高。在实际应用过程中,把VC的C语言或C + + 语言的程序作为前端客户机程序,它从Matlab 引擎接收数据信息,并与引擎传递命令的数据信息。表1是几种常用的Matlab引擎调用函数。 表1 Matlab引擎常用调用函数 通过Matlab引擎用户可以完成以下任务:首先,可以将Matlab作为一个功能强大的和可编程的数学函数库,调用Matlab中的大量的数学计算函数,完成复杂的计算任务;其次,可以为一个特定的任务构建一个完整的系统,前台的用户界面用高级语言编写,后台的计算任务由Matlab引擎来完成;最后,用户不但可以在本地计算机上调用Matlab引擎,而且还可以通过网络调用其它计算机上的Matlab引擎,这样可以很好的实现资源的共享和作业的分工合作。 3、Matlab引擎实现VC和Matlab混合编程的步骤 要想在VC集成环境下利用Matlab引擎实现VC和Matlab的混合编程, 一般需要经过以下几个必要的步骤: (1)Visual C++6.0 编译环境的设置:通过菜单 Tools/ Options,打开Visual C++6.0设置属性页,进入 Directorie页面,在 Show Directories for下拉列表中选择Include Files,添加路径:D:\Matlab6p5\extern\include(在Matlab的安装路径下);再选择下拉列表中的 Library Files,添加路径:D:\Matlab6p5\extern\ lib\win32\Microsoft\msvc60(在Matlab的安装路径下)。编译环境只需设置一次。 (2)添加库文件: 通过菜单 Projects|settings,进入 Link 页面,在 Object/Library Modules 框中,添加库文件名:libmx.lib 、libmat.lib 、libeng.lib。每个新的工程文件都要单独添加库文件。 (3)在使用 engine 函数的程序头文件中包含如下两个头文件: #include "engine.h" #include <stdlib.h> (4)在应用程序中添加调用Matlab引擎的程序代码: { Engine *ep; if(!(ep=engOpen(" \0"))) //打开Matlab引擎,建立与本地Matlab的连接 { fprintf(stderr,"\n Can't start MATLAB engine\n"); exit(-1); } 以上步骤是对VC与Matlab混合编程的编译环境进行设置,在完成了以上基本步骤后就可以利用Matlab引擎库函数engEvalString来调用Matlab的内建函数了。 根据上面的方法,下面通过一个具体的实力来说明如何实现VC与Matlab混合编程、它们之间的数据通信以及VC环境下对Matlab命令的调用。 首先,利用VC++6.0的MFC建立一个单文档结构的应用程序,加入一个菜单资源,为其映射相应的功能函数; 其次,根据Matlab引擎实现VC和Matlab的混合编程步骤(见第三部分)为程序设置相应的编译环境并添加连接库函数; 然后,调用Matlab的内建函数和命令,主要编写程序代码如下: … static double Areal[6]={1,2,3,4,5,6}; mxArray *T=NULL,*a=NULL,*d=NULL; double time[10]={0,1,2,3,4,5,6,7,8,9}; T=mxCreateDoubleMatrix(1,10,mxREAL); memcpy((char*)mxGetPr(T),(char*)time,10*sizeof(double)); engPutVariable(ep,"T",T); engEvalString(ep,"D=.5.*(-9.8).*T.^5;"); engEvalString(ep,"plot(T,D);"); … 最后,添加头文件:编译运行,就可以得到如(图1)所示的结果。 图1 调用Matlab引擎输出结果 上面例子是VC和Matlab的混合编程的一个简单应用,在实际的数值计算,控制系统开发等工程应用中,可以很好的利用VC和Matlab的混合编程技术,从而简化应用程序的开发工作量。 5、结论 Matlab提供了强大的数学计算功能和丰富的工具箱, 使用VC和Matlab的混合编程, 可以发挥各自特长, 缩短工程应用软件的开发周期, 同时也提高了程序的运行效率。其中,基于客户机/服务器计算模式的Matlab引擎是实现VC与Matlab 混合编程的一种常用方法。通过对引擎调用与数据组织方式的面向对象的设计,将数据组织透明化,极大地简化了程序设计过程, 封装了对Matlab 引擎的访问和与Matlab 服务器进行数据交换的细节,为用户提供了一个友好的编程接口环境。 http://hi.baidu.com/ysuwjl/blog/item/cb4fe68055d056c8bd3e1eb8.html 【转】VC调用matlab中定义的.m文件中的函数的实例 -----这个写得比较清楚 Matlab是一个强大的数学计算/仿真工具,其内置了很多实用的现成的函数,而且我们经常也自己定义很多m函数。但在很多情况下,我们不得不使用VC编程。那么,如何在VC中利用matlab的资源呢?在这里我简要的以一个简单的例子来说明一下如果在VC中调用matlab中定义的.m文件。繁多的理论就不说了,简明扼要的说一个实例。相信大家看过之后都会马上学会的J 其中灰色底显示的部分是需要我们手工输入的部分。 步骤如下: ㈠当然是先建立 matlab 的 m 文件。 这里为了简单起见,我在matlab中定义了一个函数,其m文件如下: function y = add_zh(a,b) y=a+b 保存为myfunct.m ㈡下面来对 matlab 编译环境进行设置。打开matlab,在命令行状态下键入:mex-setup 然后出现如下提示: -------------------------------------------------------------------------------------- Select a compiler: [1] Borland C++Builder version 5.0 in C:\Program Files\Borland [2] Lcc C version 2.4 in F:\SOFT\SHARE\MATLAB65\sys\lcc [3] Microsoft Visual C/C++ version 6.0 in C:\Program Files\Microsoft Visual Studio [0] None Compiler: -------------------------------------------------------------------------------------- 这里我们选择’3’。(如果使用其他的编译器比如BCB,那么就可以相应的选择’1’) 然后,继续在命令行状态下输入: mbuild –setup -------------------------------------------------------------------------------------- Please choose your compiler for building standalone MATLAB applications: Would you like mbuild to locate installed compilers [y]/n? y Select a compiler: [1] Borland C++Builder version 5.0 in C:\Program Files\Borland [2] Lcc C version 2.4 in F:\SOFT\SHARE\MATLAB65\sys\lcc [3] Microsoft Visual C/C++ version 6.0 in C:\Program Files\Microsoft Visual Studio [0] None Compiler: -------------------------------------------------------------------------------------- 这里需要几步确认。大家按情况操作即可。 ㈢对 VC 的编译器环境进行设置。在Tools-options-directory里面设置include和lib的路径,分别添加一项,指向matlab安装目录中的\extern\include和 \extern\lib ㈣这一步比较关键。在这一步中,将 matlab 中的 .m 文件转换为 dll 。 在matlab命令行中输入: mcc -t -h -L C -W lib:ppp -T link:lib myfunct.m 至此,可以发现在myfunct.m所在的目录中产生了一大堆文件。我们只用其中3个: ppp.h ppp.lib ppp.dll ㈤新建一个 VC 工程 。这里取名为 mat 。为了简单,我们在这里建立一个对话框来进行演示。如下: 然后,将上面这3个文件拷贝到VC工程所在的目录中,以便VC调用之。 ㈥进行 VC 编程。 首先,在cpp文件中加入: #include “ppp.h” 然后,设置VC的链接库。在project-settings-link下的object/library modules中加入: ppp.lib libmx.lib libmatlb.lib libmmfile.lib 至此,VC的编译环境设置完毕。下面就是编程部分了。 ㈦编程部分的关键:接口和数据类型的转换 先给出 VC 实现的源代码: ------------------------------------------------------------------------ void CMatDlg::OnButton1() { // 在 matlab 中定义的 m 文件 :myfunct ,其功能是完成两个数的相加操作。 CString str; UpdateData(true); pppInitialize(); // 为了调用 matlab 中的函数,必须使用数组数据类型,并其后调用 matlab 函数将其转化为矩阵格式( matlab 的基本数据类型是矩阵) static double x1[1]={1.0}; static double x2[1]={2.5}; double result; // 调用 matlab 创建 3 个矩阵 mxArray *A=mclGetUninitializedArray(); mxArray *B=mclGetUninitializedArray(); mxArray *C=mclGetUninitializedArray(); // 将 C 语言中的变量值赋给 matlab 中的矩阵 mlfAssign(&A,mlfDoubleMatrix(1,1,x1,NULL)); mlfAssign(&B,mlfDoubleMatrix(1,1,x2,NULL)); mlfAssign(&C,mlfMyfunct(A,B)); // 将 matlab 中的矩阵的指针传递给 C 语言中的指向 double 的指针 double * md=mxGetPr(C); result=md[0]; // 释放这些矩阵 mxDestroyArray(A); mxDestroyArray(B); mxDestroyArray(C); str.Format ("It is : %f",result); ::AfxMessageBox(str); } ------------------------------------------------------------------------ 相信看到里面的注释,我们就明白的差不多了。 VC 编程以实现对 matlab 函数的调用,例如 VC 中我们实现两个 double 型的相加,则需要做上述的编程:首先定义两个数组并存入我们要进行函数操作的数据(也就是所谓的实参);然后将这两个数组转换为 matlab 可以识别的矩阵;然后调用 m 文件中自定义的函数,对矩阵进行操作;最后将结果再转回 VC 支持的数据格式: double * md=mxGetPr(C); result=md[0]; 至此,经 matlab 函数处理过的数据已经存入了 VC 中的 result 变量。 mlfAssign(&C,mlfMyfunct(A,B)); 大家可以看出来,在进行调用的时候,我们使用的是 m 文件的文件名 myfunct ,而不是 m 文件中定义的 add_zh(a,b) http://www./edaiqingwa/archive/2009/08/01/20741.html 【转】vs调用通过dll调用matlab程序 ----这个也讲的很详细,而且是直接用vs2005举例的,不错 程序中使用MATLAB编译产生的DLL (VS2005, MATLAB7.5, mwArray) 实验内容:把一个简单的m代码编译成C++接口的DLL,然后在C++程序中调用。为了简单起见,这里的C++程序是一个Win32 Console程序,而不是Windows图形界面的程序,不过不妨碍我们的讨论。 下面是这个例子用到的m代码。它定义了一个名为myadd2的函数: CODE: function [y,z] = myadd2(a, b) % dummy function, just to demonstrate the idea y = a+b; z = a+2*b; end 首先把这个函数编译成C++接口的DLL。为此,我们需要先设置MATLAB编译器。具体做法是在MATLAB命令行执行“mbuild -setup”。然后用下面这行命令把myadd2函数编译成一个C++接口的DLL: CODE: mcc -W cpplib:libmyadd2 -T link:lib myadd2 结果,我们将会得到包含libmyadd2.dll,libmyadd2.ctf,libmyadd2.h,libmyadd2.lib等在内的一些文件。接下来我们只需要这四个文件。请注意:在MATLAB R2007b之前,这些文件都会在和编译的m代码所在的目录中,而在MATLAB R2007b,缺省情况下这些文件会在Documents and Settings中用户的My Documents目录中。 然后在VS2005中创建一个Win32 Console的VC++工程,我在测试时取名为testmyadd2_r2007b。把以上四个(全部文件)文件拷贝到VC++工程的源代码所在目录。 接下来设置VC++,让它能找到MATLAB接口函数的定义及连接库函数。可以有两种设置方式:一种是改VS2005中关于VC++的设置,这样的好处是每个新的工程都能自动获得这个设定;而另一种是只改当前工程的设置,也就是设置只对该工程有效。这里用后一种方式。 在VS2005中打开工程testmyadd2_r2007b,选择菜单“Project-->Properties,在出来的对话框上,把MATLAB提供的include路径加到VC++的头文件搜索路径。如图所示: D:\MATLAB7\extern\include 然后把相应的lib所在目录加到linker的额外搜索路径上。如图所示: D:\MATLAB7\extern\lib\win32\microsoft\msvc71 接下来,告诉VC++,我们的这个程序需要连接到另外两个额外的库函数:libmyadd2.lib和mclmcrrt.lib。中间用空格隔开。如图所示: 最后则是程序代码。这个程序只有一个main函数 CODE: #include "stdafx.h" #include #include "mclmcr.h" #include "mclcppclass.h" #include "libmyadd2.h" int _tmain(int argc, _TCHAR* argv[]) { std::cout << "Hello world!" << std::endl; if( !mclInitializeApplication(NULL,0) ) { std::cout << "Could not initialize the application!" << std::endl; return -1; } // initialize lib if( !libmyadd2Initialize()) { std::cout << "Could not initialize libmyadd2!" << std::endl; return -1; } try { // declare and initialize a mwArray a(2, 2, mxDOUBLE_CLASS); double *aData; aData = new double[4]; int i; for( i=0; i<4; ++i) { aData[i] = 1.0*i; } // print output std::cout << "a = " << std::endl; std::cout << aData[0] << ", " << aData[1] << std::endl; std::cout << aData[2] << ", " << aData[3] << std::endl; a.SetData(aData, 4); // declare and initialize b mwArray b(2, 2, mxDOUBLE_CLASS); b(1,1) = 11.; b(1,2) = 12.; b(2,1) = 21.; b(2,2) = 22.; mwArray y(2, 2, mxDOUBLE_CLASS); mwArray z(2, 2, mxDOUBLE_CLASS); // call the function myadd2(2, y, z, a, b); // copy data from mwArray to C++ objects // allocate outputs double *yData, *zData; yData = new double[4]; if( yData == NULL ) { std::cout << "Failed to allocate memory for yData!" << std::endl; return -1; } zData = new double[4]; if( zData == NULL ) { std::cout << "Failed to allocate memory for zData!" << std::endl; return -1; } // copy data from mwArray to C++ y.GetData(yData, 4); z.GetData(zData, 4); // print output std::cout << "y = " << std::endl; std::cout << yData[0] << ", " << yData[1] << std::endl; std::cout << yData[2] << ", " << yData[3] << std::endl; std::cout << "z = " << std::endl; std::cout << zData[0] << ", " << zData[1] << std::endl; std::cout << zData[2] << ", " << zData[3] << std::endl; // deallocate memory delete [] aData; delete [] zData; delete [] yData; } catch( const mwException& e) { std::cerr << e.what() << std::endl; } // terminate the lib libmyadd2Terminate(); // terminate MCR mclTerminateApplication(); return 0; } 实验的结果表明,在C++程序中使用MATLAB编译产生的C++接口DLL非常容易。 error:mcc编译m文件出现这样的错误提示(例): Error: File "psf3" is a script M-file and cannot be compiled with the current Compiler. matlab complier不能编译script M-file,请将script M-file转成function m-file 最简单的一个转法是:如果你的m文件叫a.m,在开头加上一句: function a http://hi.baidu.com/minedreamflowers/blog/item/70593b24b5da913bc9955914.html 果然,实践才是检验真理的唯一标准啊,弄了一天,发现以上文章中都有不同程度的问题,最后按照另一篇文章的做法才把这个例子弄通了,额,囧啊~~ 【转】VS2008 C++ 调用MATLAB 2009b 生成的DLL 刚开始学习用VC++调用matlab生成的DLL,找了网上一些资料,难以找到vs2008与MATLAB2009b版本的,按照以往版本做的总是有很多错误。经过两天努力,终于调试成功,这里将经验总结一下,以供有需要的人们参考。 实验环境: Win7 MATLAB 2009b(安装路径:E:\Program Files\MATLAB\R2009a) VS2008 中文版(安装路径:E:\Program Files\Microsoft Visual Studio 9.0) 1.Matlab 生成DLL 1.1编译器的安装 在matlab中先安装编译器,我在第一次安装的时候一路y下来,只有一个compiler,还是最老的。这教育我们要学会说N,按照以下步骤操作 >> mbuild -setup Please choose your compiler for building standalone MATLAB applications: Would you like mbuild to locate installed compilers [y]/n? n Select a compiler: [1] Lcc-win32 C 2.4.1 [2] Microsoft Visual C++ 6.0 [3] Microsoft Visual C++ .NET 2003 [4] Microsoft Visual C++ 2005 SP1 [5] Microsoft Visual C++ 2008 Express [6] Microsoft Visual C++ 2008 SP1 [0] None Compiler: 6 The default location for Microsoft Visual C++ 2008 SP1 compilers is C:\Program Files\Microsoft Visual Studio 9.0, but that directory does not exist on this machine. Use C:\Program Files\Microsoft Visual Studio 9.0 anyway [y]/n? n Please enter the location of your compiler: [C:\Program Files\Microsoft Visual Studio 9.0] e:\Program Files\Microsoft Visual Studio 9.0 (红色部分换成你的vs所安装的地址) Please verify your choices: Compiler: Microsoft Visual C++ 2008 SP1 Location: e:\Program Files\Microsoft Visual Studio 9.0 Are these correct [y]/n? y **************************************************************************** Warning: Applications/components generated using Microsoft Visual Studio 2008 require that the Microsoft Visual Studio 2008 run-time libraries be available on the computer used for deployment. To redistribute your applications/components, be sure that the deployment machine has these run-time libraries. **************************************************************************** Trying to update options file: C:\Users\Administrator\AppData\Roaming\MathWorks\MATLAB\R2009a\compopts.bat From template: E:\PROGRA~1\MATLAB\R2009a\bin\win32\mbuildopts\msvc90compp.bat Done . . . 1.2 DLL的生成 首先新建一个m文件,文件名为myadd2.m,定义了一个名为myadd2的函数,代码如下: ////////////////////////////////////////////////////// function [y,z] = myadd2(a, b) % dummy function, just to demonstrate the idea y = a+b; z = a+2*b; end ///////////////////////////////////// 在MATLAB命令框中输入以下命令: mcc -W cpplib:libmyadd2 -T link:lib myadd2.m 生成libmyadd2.lib, libmyadd2.h, libmyadd2.dll 等文件,将这三个文件拷到VS的项目目录下 2. VS调用DLL 2.1 新建一个项目,并设置环境 新建一个win32 控制台应用程序,我取的名字是matlabDll2.当然新建其他的项目类型也可以,我这只是个例子。接下来进行配置,在该项目的属性中进行了配置,只对该项目有效。若建新的项目需要重新配置。项目建好后将libmyadd2.lib, libmyadd2.h, libmyadd2.dll拷贝到项目目录下。 首先配置项目属性页/配置属性/C-C++/常规/附加包含目录,请根据自己电脑上软件的安装位置对照设置,2008与2005不同的地方时这里要加两个目录,如下图所示: 其次配置项目属性页/配置属性/链接器/常规/附加库目录,请根据自己电脑上软件的安装位置对照设置,如下图所示: 然后配置项目属性页/配置属性/链接器/输入/附加依赖性,填入libmyadd2.lib mclmcrrt.lib mclmcr.lib ,如下图所示: 在这一步俺可吃了大苦头了,有篇文档只说添加前两项,俺就照做了,结果导致运行失败,找了好长时间也没发现错误,两天的功夫都在找,结果就是因为少填了这一项,还有其他的一些包含lib,比如libmex.lib libmx.lib ,这里没填,好像是VC6上要配的。 配置到此结束 2.2 编写主程序,调试运行 这段代码是从别处拷来的,是一段完整代码,将它粘到matlabDLL2.cpp 主CPP文件中,调试通过: ////////////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include <iostream> #include "mclmcr.h" #include "mclcppclass.h" #include "libmyadd2.h" int _tmain(int argc, _TCHAR* argv[]) { std::cout << "Hello world!" << std::endl; // initialize lib if( !libmyadd2Initialize()) { std::cout << "Could not initialize libmyadd2!" << std::endl; return -1; } try { // declare and initialize a mwArray a(2, 2, mxDOUBLE_CLASS); double *aData; aData = new double[4]; int i; for( i=0; i<4; ++i) { aData[i] = 1.0*i; } // print output std::cout << "a = " << std::endl; std::cout << aData[0] << ",\t" << aData[1] << std::endl; std::cout << aData[2] << ",\t" << aData[3] << std::endl; a.SetData(aData, 4); // declare and initialize b mwArray b(2, 2, mxDOUBLE_CLASS); b(1,1) = 11.; b(1,2) = 12.; b(2,1) = 21.; b(2,2) = 22.; mwArray y(2, 2, mxDOUBLE_CLASS); mwArray z(2, 2, mxDOUBLE_CLASS); // call the function myadd2(2, y, z, a, b); // copy data from mwArray to C++ objects // allocate outputs double *yData, *zData; yData = new double[4]; if( yData == NULL ) { std::cout << "Failed to allocate memory for yData!" << std::endl; return -1; } zData = new double[4]; if( zData == NULL ) { std::cout << "Failed to allocate memory for zData!" << std::endl; return -1; } // copy data from mwArray to C++ y.GetData(yData, 4); z.GetData(zData, 4); // print output std::cout << "y = " << std::endl; std::cout << yData[0] << ",\t" << yData[1] << std::endl; std::cout << yData[2] << ",\t" << yData[3] << std::endl; std::cout << "z = " << std::endl; std::cout << zData[0] << ",\t" << zData[1] << std::endl; std::cout << zData[2] << ",\t" << zData[3] << std::endl; // deallocate memory delete [] aData; delete [] zData; delete [] yData; } catch( const mwException& e) { std::cerr << e.what() << std::endl; } // terminate the lib libmyadd2Terminate(); // terminate MCR mclTerminateApplication(); return 0; } ///////////////////////////////////////////////////////////////////////////// 运行结果如下图: 问题 我将代码的标红部分注释掉了,否则会出现错误: 1>c:\users\administrator\documents\visual studio 2008\projects\matlabdll2\matlabdll2\matlabdll2.cpp(14) : error C3861: “mclInitializeApplication_proxy”: 找不到标识符 我不知道为什么,大家在调试的过程如果解决了这个问题,麻烦告诉一声:liufengjk_ok@126.com。 致谢 感谢taohe等网友提供的参考! http://blog.csdn.net/infocarrier/archive/2010/09/01/5854522.aspx
|
|
来自: 叶喜勇图书馆 > 《matlab应用》