技术蛀虫

导航

VC++与Matlab混合编程2

在VC中调用MATLAB的,总结有以下几种方法:1、是调用Matlab引擎;2、是调用Matlab中M函数转化成的dll文件;3、调用Matlab中M函数转化成c语言的函数。

  第一种方法

 一、设置VC相关属性。

    (1)Visual C++6.0 编译环境的设置:通过菜单 Tools/ Options,打开Visual C++6.0设置属性页,进入 Directorie页面,在 Show Directories for下拉列表中选择Include Files,添加路径:<matlab>\extern\include(在Matlab的安装路径下);再选择下拉列表中的 Library Files,添加路径:<matlab>\extern\ lib\win32\Microsoft(在Matlab的安装路径下,但是在我查看资料的时候看到很多是<matlab>\extern\ lib\win32\Microsoft\msvc60这个路径,但是我用的是MatlabR2009a,或许这里设置有点区别)。看资料说编译环境或许只需设置一次,但是我在设置的时候每次都要设置。

    (2)添加库文件: 通过菜单 Projects|settings,进入 Link 页面,在 Object/Library Modules 框中,添加库文件名:libmx.lib 、libmat.lib 、libeng.lib。每个新的工程文件都要单独添加库文件。

 二、在VC中通过MATLAB引擎调用Matlab函数命令:

          现在以画一个正弦曲线的图为例。

         1、 新建一个MFC程序,命名Test,基于对话框。

          
        2、在Testdlg.cpp中加入头文件:

#include "engine.h"
#include <stdlib.h>

        3、添加botton  Test,并添加点击命令,加入代码如下:

void CTestDlg::OnTest()
{
 // TODO: Add your control notification handler code here
 Engine *ep;
 
 if (!(ep = engOpen(NULL))) //打开Matlab引擎

 {              

     MessageBox ("Can't start MATLAB engine", MB_OK);

     exit(-1);

 } 

 engSetVisible(ep, 0);
 
 engEvalString(ep,"x=0:0.001:2*pi;");
 
 engEvalString(ep,"y=sin(x);");     
 
 engEvalString(ep,"plot(x,y)");//会显示出图
}

        4、运行程序,单击Test按钮,运行结果如下图:

        

至此,利用VC调用Matlab引擎结束,可以运行Matlab中的各种函数,作图等。此种方法的特点是,非常简单和方便,要求运行程序的电脑必须装有Matlab软件,因此也具有不能脱离Matlab环境的弱点。

备注:此次测试是基于Visual C++6.0和Matlab R2009a的环境。

上面例子是VC和Matlab的混合编程的一个简单应用,在实际的数值计算,控制系统开发等工程应用中,可以很好的利用VC和Matlab的混合编程技术,从而简化应用程序的开发工作量。

 

 

 

第二种方法:利用Matlab生成DLL文件,然后用VC调用DLL文件,此种方法是将Matlab写的函数封装在动态链接库里面,然后用VC调用动态链接库,优点是程序的运行可以脱离Matlab的环境独立运行。

在VC中调用MATLAB的,总结有以下几种方法:1、是调用Matlab引擎;2、是调用Matlab中M函数转化成的dll文件;3、调用Matlab中M函数转化成c语言的函数。在本文当中重点讲解第二种方法,调用Matlab中M函数转换成DLL文件的形式。
在我自己编写之前,查看了很多的文献,但是每个文献所应用的Matlab的版本不一样,很多数学函数对应的库不一样,导致最终的函数出错,本次练习和测试也是出现在了一个lib文件没有找到问题,查找了很长时间,一个一个的对出来才找到的错的原因。
因此在开始我们编程之前想告诉大家的是,我们在中间过程当中可能会遇到很多的问题,但是这个时候一定要坚持下去,多查文献,同时积极向高手请教,只有这样才能做出成品,不然的话我们只能中途而废。好了,现在开始正文。
在VC6.0下调用Matlab的M文件,基本可以分为一下几个大步骤,1、对Matlab的编译环境进行配置;2、编写M函数生成DLL文件;3、编写VC程序,对工程进行配置;4、调用生成的DLL文件中的函数;5、程序的调试和发布。
一、Matlab编译环境的设置
为了在开发时实现对MATLAB的具体功能的调用,应首先在操作系统中安装MATLAB工具软件,之后并运行此工具软件,依次执行
mex –setup
mbuild –setup
此时一定要注意横线前面的空格,最好不要复制,自己手工输入到Matlab的命令对话框当中,不然会出现错误,很多人在这里遇到了问题。
>> mex -setup
Please choose your compiler for building external interface (MEX) files: 
 
Would you like mex to locate installed compilers [y]/n? 
 
Select a compiler: 
[1] Lcc-win32 C 2.4.1 in D:\PROGRA~1\MATLAB\R2009a\sys\lcc 
[2] Microsoft Visual C++ 6.0 in D:\Program Files\Microsoft Visual Studio 
 
[0] None 
 
Compiler: 2
 
Please verify your choices: 
 
Compiler: Microsoft Visual C++ 6.0 
Location: D:\Program Files\Microsoft Visual Studio 
 
Are these correct [y]/n? 
 
Trying to update options file: C:\Users\Robin\AppData\Roaming\MathWorks\MATLAB\R2009a\mexopts.bat 
From template:              D:\PROGRA~1\MATLAB\R2009a\bin\win32\mexopts\msvc60opts.bat 
 
Done . . . 
 
************************************************************************** 
  Warning: The MATLAB C and Fortran API has changed to support MATLAB 
           variables with more than 2^32-1 elements.  In the near future 
           you will be required to update your code to utilize the new 
           API. You can find more information about this at: 
           http://www.mathworks.com/support/solutions/data/1-5C27B9.html?solution=1-5C27B9
           Building with the -largeArrayDims option enables the new API. 
************************************************************************** 
 
>>
以上是运行mex –setup的情况。
>> mbuild -setup
Please choose your compiler for building standalone MATLAB applications: 
 
Would you like mbuild to locate installed compilers [y]/n? 
 
Select a compiler: 
[1] Lcc-win32 C 2.4.1 in D:\PROGRA~1\MATLAB\R2009a\sys\lcc 
[2] Microsoft Visual C++ 6.0 in D:\Program Files\Microsoft Visual Studio 
 
[0] None 
 
Compiler: 2
 
Please verify your choices: 
 
Compiler: Microsoft Visual C++ 6.0 
Location: D:\Program Files\Microsoft Visual Studio 
 
Are these correct [y]/n? 
 
Trying to update options file: C:\Users\Robin\AppData\Roaming\MathWorks\MATLAB\R2009a\compopts.bat 
From template:              D:\PROGRA~1\MATLAB\R2009a\bin\win32\mbuildopts\msvc60compp.bat 
 
Done . . . 
 
>>
以上为运行mbuild –setup的情况。
二、写M函数,创建动态链接库(*.DLL)
1、创建动态链接库主要有两种方法:
一种是使用 Matlab为VC++ IDE提供的Add-in。这种方法比较简单,方便快捷,只要 在VC++中创建工程的时候选择Matlab Project Wizard,并且在接下来的Step1中的Visual Matlab Application Type 选择 Shared M-DLL就可以了。接下来就是添加*.m文件, 进行编 译 了。
另一种方法就是使用Matlab的mcc命令将*.m文件编译为动态链接库(*.DLL)。
mcc–B csglsharedlib: youlibname function1 funcion2…来创建我们所需要的动态链接库 DLL文件。其中参数-B表示使用的是Bundle Files作为参数,csglsharedlib是-B的参数,意 思是生成使用Matlab图形库的C共享动态链接库,youlibname是你想要生成的动态链接库 DLL的文件名,注意csglsharedlib与youlibname之间有一个冒号“:”连接,function1为你想要加入到动态链接库DLL中的函数名,如果有多个函数,各个函数名用空格隔开。
举例:创建所需的Matlab函数文件 MyAdd.m
function [c] = MyAdd(a, b);  
c = a + b; 
然后,进行编译,命令如下:
mcc -W cpplib:libMyAdd -T link:lib MyAdd
其中,mcc是Matlab提供的编译命令,对于这一点,Matlab的帮助说明如下:
-W lib:string link:lib其中-W是控制编译之后的封装格式,cpplib,是指编译成C++的lib,cpplib冒号后面是指编译的库的名字,-T表示目标,link:lib表示要连接到一个库文件的目标,目标的名字是后面的MyAdd,即你写的m函数的名字。
运行完之后,你的目录下面,将会出现以下一些文件:
libMyAdd.cpp
libMyAdd.exp
libMyAdd.dll
libMyAdd.exports
libMyAdd.h
libMyAdd.prj
libMyAdd_mcc_component_data.c
mccExcludedFiles.log
readme.txt
具体每一个文件的意思,请查帮助,这里只说其中很有用的几个:
libMyAdd.dll是编译好的动态库,MyAdd这个函数封装在里面,libMyAdd.h是对应的头文件,在C里面调用这个函数的时候,需要include这个头文件,在这个头文件的最后,你可以看到下面的内容:
extern LIB_libMyAdd_CPP_API void MW_CALL_CONV MyAdd(int nargout, mwArray& c, const mwArray& a, const mwArray& b);
这就是MyAdd的C函数的声明。nargout表示输出变量的个数,a,b,c就是对应了m函数的几个变量。
注意,a,b,c三个变量的类型是mwArray,这是Matlab提供的一个特殊的变量类型(在7.0的版本,编译之后,变量类型是mxArray)。mwArray是一个类,具体可以查帮助,当然后面也会讲到。
三、在VC++中使用Matlab生成的动态链接库(*.DLL)
首先新建一个基于MFC的对话框程序,太简单了,取名为Add,然后进行如下设置:
 
1、设置 Include 和 Library 目录
在VC++IDE中选择Tools->Options->Directories。
在 Show directoris for:中选择Include files,添加如下两个目录:
 

在 Show directoris for:中选择Library files,添加如下两个目录:
 
这里假设<Matlab>为你的Matlab的安装目录。这些操作只需要一次。以后的工程中不需再进行操作。
2、工程 (project)本身的一些设置 
在 VC++ IDE中选择 Project->Setting->Link
在Category中选择General,在Object/library modules中添加mclmcrrt.lib libmx.lib libmat.lib mclmcr.lib libMyAdd.lib
 
3、为工程添加相应的文件
把刚才生成的libMyAdd.h libMyAdd.dll libMyAdd.lib文件复制到VC++工程的文件夹下,并且用add to project//files… 添加的工程中(如果遇到添加文件到工程的命令没有反应的时候可以尝试将Office卸载掉,我在编程的时候就遇到了这个问题)。
 4、使用DLL
(1)首先要在使用DLL中函数的源文件中加上头文件libMyAdd.h。如下再加上另外两个数学函数的头文件:
#include "mclmcr.h"   
#include "matrix.h"
#include "libMyAdd.h"
(2)注册DLL
在使用之前还需要对libMyAdd.dll进注册,使用完毕之后需要对其进行释放。注册使用函数libMyAddInitiallize();释放使用函数libMyAddTerminate()。
函数名的规则就是youlibname+Initialize(Terminate)。 这两函数在libMyAdd.h 中可以找到。
libMyAddInitialize()不仅注册了刚才生成的libMyAdd.dll,同时它也注册了Matlab本身的一些动态链接库(*.DLL);同理libMyAddTerminate()不仅释放了刚才生成的libMyAdd.dll,同时它也释放了Matlab本身的一些动态链接库(*.DLL)。因此在注册了libMyAdd.dll之后,我们也可以使用 Matlab的数学库中的函数,例如mlfabs(),mlfAssign()等等 。 
在使用libMyAdd.dll 的时候,存在着一个VC++和libMyAdd.dll中的函数之间数据交互的问题 。
由于libMyAdd.dll中的函数所接受的参数是mxArray 型数据 。因此我们要使用Matlab为 我们提供的External Interfaces/ API 函数来创建mxArray 型数据,大量的API函数可参见Matlab 的帮助文件Matlab\External Interfaces/API Reference\C MX-Functionsx 小节。还有一个需要注意的问题就是原来的函数名myfun 变成了mlfMyfun。可以在libMyAdd.h中看到。
下 面 就是一个 实 例 
void CAddDlg::OnAdd() 
{
 // TODO: Add your control notification handler code here
 double a = 6;   
 double b = 8;   
 double c; 
 if(!libMyAddInitialize())   
 {   
  MessageBox("Could not initialize libMyAdd!");   
  exit(-1); 
 }  
 mwArray mwA(1, 1, mxDOUBLE_CLASS);
 mwArray mwB(1, 1, mxDOUBLE_CLASS);  
 mwArray mwC(1, 1, mxDOUBLE_CLASS);   
 mwA.SetData(&a, 1);   
 mwB.SetData(&b, 1);
 MyAdd(1, mwC, mwA, mwB);  
 c = mwC.Get(1, 1);   
 CString str;
 str.Format("%.0f",c);
 MessageBox(str,"求和结果");
 libMyAddTerminate();  
}
四、对程序进行运行和调试
 调试结果如下图:

posted on 2012-04-07 08:38  技术蛀虫  阅读(2701)  评论(0编辑  收藏