zoukankan      html  css  js  c++  java
  • 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();  
    }
    四、对程序进行运行和调试
     调试结果如下图:

  • 相关阅读:
    VS安装部署
    C#与C/C++的交互
    3、C#入门第3课
    登录接口,猜年龄
    安装sql server 2016 always on配置dtc支持时遇到的问题
    购物车第一版
    Oracle patch查看路径
    innobackup增量备份脚本
    在vmware workstation下安装linux6关闭防火墙
    线程池-连接池-JDBC实例-JDBC连接池技术
  • 原文地址:https://www.cnblogs.com/nktblog/p/2435624.html
Copyright © 2011-2022 走看看