MATLAB编程与应用系列-第16章 外部接口技术(5)

本章教程共分为7篇进行阐述:
MATLAB编程与应用系列-第16章 外部接口技术(1)
MATLAB编程与应用系列-第16章 外部接口技术(2)
MATLAB编程与应用系列-第16章 外部接口技术(3)
MATLAB编程与应用系列-第16章 外部接口技术(4)
MATLAB编程与应用系列-第16章 外部接口技术(5)
MATLAB编程与应用系列-第16章 外部接口技术(6)
MATLAB编程与应用系列-第16章 外部接口技术(7)

本系列教程来源于出版书籍《基于MATLAB编程基础与典型应用书籍》,如涉及版权问题,请联系:156204968@qq.com。 出版社:人民邮电出版社, 页数:525。

本系列教程目前基于MATLABR2006a,可能对于更高级版本的功能和函数有差异,教程中如有问题,请联系:156204968@qq.com

16.5 Visual C++与MATLAB接口

MATLAB开发环境提供了丰富的应用程序接口(API)库函数实现C,C++与MATLAB的混合编程,通过mex, mbuild, mcc编译命令可以实现把M文件编译成Visual C++环境下直接调用的C/C++文件,或者把C文件编译成在MATLAB开发环境中直接调用的可执行文件。在Visual C++中实现和MATLAB开发环境的接口主要有以下几种方法:

  • 在Visual C++中使用MATLAB引擎,调用应用程序接口(API)中的Engine函数库,调用MATLAB函数,但是该方法在编译成功后,会自动启动MATLAB开发环境,在16.4节MATLAB引擎技术一节中有详细介绍;

  • 在Visual C++中直接调用MATLAB语言C, C++数学函数库(Math Library),通过mex和mbuild命令配置MATLAB语言C/C++开发环境,实现Visual C++和MATLAB的接口,编译形成独立与MATLAB环境的可执行.exe文件;

  • 使用C/C++语言编写MEX文件,在MATLAB中通过MEX命令编译成MATLAB可以直接运行的文件,以实现Visual C++与MATLAB的接口,在16.2节MEX文件介绍中,已经作了详细的探讨。

  • 使用MathTools公司开发的MATCOM可视化界面,将MATLAB文件编译成Visual C++可以直接执行的C++文件,生成的C++文件可以同时兼顾MATLAB开发环境强大的数学运算功能和C++语言运行速度快两方面的优点。使用Visual MATCOM Add-in插件,在Visual C++环境中直接编译运行M文件。

  • 使用COM((Component Object Model)组件可以实现MATLAB与Visual C++的接口。 通过MATLAB COM Builder可以把MATLAB开发的M文件,MEX文件等做成组件,使之成为独立的COM对象,可以被其他支持COM语言的开发环境所使用,如Visual C++,Visual Basic,JAVA,Microsoft EXCEL等。

本节主要介绍通过配置Visual C++编译环境,编译运行MEX文件,MAT文件,调用MATLAB C++数学函数库,在Visual C++中使用MATLAB引擎,基于MATCOM实现Visual C++通MATLAB的接口,利用MATLAB COM Builder可视化界面实现Visual C++和MATLAB的接口。主要内容包括:

  • Visual C++中使用MATLAB引擎

  • Visual C++中使用MATLAB语言数学函数库

  • Visual C++中创建MAT文件

  • 基于MATCOM实现Visual C++与MATLAB接口

  • 使用COM组件实现Visual C++和MATLAB接口

16.5.1 Visual C++中使用MATLAB引擎

在16.4节MATLAB引擎技术一节中,详细介绍了在Visual C++环境下调用MATLAB引擎的环境配置和实例演示,利用MATLAB应用程序接口(API)函数库的Engine函数库可以直接调用MATLAB开发环境函数,一方面可以保持C++代码的运行效率,同时可以使用MATLAB丰富的数学函数库函数,各种工程领域工具箱函数等。但是使用MATLAB引擎技术,生成的应用程序无法独立与MATLAB平台运行,通过这种方式进行MATLAB函数调用,必须要求系统安装MATLAB安装程序,这给应用程序的移植和推广带来难度。以下介绍的一些Visual C++与MATLAB接口技术,可以实现将MATLAB函数编译成.exe文件,动态链接库文件DLL文件或者编译成COM组件,可以独立与MATLAB开发平台运行。

16.5.2 Visual C++中使用MATLAB语言C,C++数学函数库

MATLAB开发环境的C,C++数学函数库以mwArray结构体为数据核心,使用mcc命令将M文件转换成的C/C++文件可以直接在Viusal C++开发环境中使用,但是编译后的C,C++文件一般程序冗长,代码可读性较差。在熟练掌握C, C++数学函数库的基础上,读者可以使用mwArray结构体自行编写基于应用程序接口(API)函数库C, C++数学库的C/C++文件,可以极大优化程序代码,减少程序代码存储空间,提高程序代码的执行效率和执行速度。在下文的讲述中,将通过一个简单实例来演示如何利用mcc命令创建独立与MATLAB平台运行的exe文件。

首先使用MATLAB的M语言建立用户所需要的特定功能M 文件,在这里,为了简单而言,建立一个实现魔方阵功能的M文件magicCreat.m。

function y = magicCreat(n)
y = magic(n)

然后从%matlabroot%\ extern\examples\compiler (%matlabroot%为读者计算机系统中MATLAB的安装路径,本文中为C:\Program Files\MATLAB\R2006a\extern\examples\compiler)路径下拷贝main_for_lib.cmain_for_lib.h.到当前的工作路径下,以便mcc编译命令调用。然后创建调用magicCreat.m文件的C语言程序如下:

#include <stdio.h>
#include <math.h>
#include "libPkg.h" //编译建立的库头文件
main( int argc, char **argv )
{
    mxArray *N;        /* 输入变量矩阵指针 */
    mxArray *R = NULL; /* 结果矩阵指针 */
    int  n; //默认的M文件输入变量数值
    /* 获取命令行参数,如果命令行输入小于2,则输入参数默认为5 */
    if (argc >= 2) {
        n = atoi(argv[1]);
    } else {
        n = 5;
    }
    //初始化MCR和libPkg函数库
    mclInitializeApplication(NULL,0);
    libPkgInitialize(); 
    /* 得到输入参量的数值 */
    N = mxCreateDoubleScalar(n); 
    /*调用magicCreat.m编译后的文件mlfMagicCreat*/
    mlfMagicCreat(1, &R, N);  
    /* 释放内存空间*/
    mxDestroyArray(N);
    mxDestroyArray(R);
    //结束libPkg库和MCR
    libPkgTerminate(); 
    mclTerminateApplication();
}

其中libPkg.h为mcc命令编译后的库文件,该文件结构清晰,首先程序代码包含相关必要的头文件和libPkg.h文件,主程序入口,变量的定义,然后初始化MCR和libPkg函数库,调用magicCreat.m编译后的文件mlfMagicCreat,调用结果用矩阵R存储,最后释放内存空间,并结束libPkg库和MCR。在程序结束之前及时地释放内存空间是一个很好的编程习惯。将该程序存储为magicCreatCFile.c,接下来使用mcc命令编译该文件,在MATLAB命令行窗口中输入:

mcc -W lib:libPkg -T link:exe magicCreat  magicCreatCFile.c main_for_lib.c

经过mcc命令编译后,可以发现在当前路径下,出现一个magicCreat.exe文件,为一个可执行程序文件,在MATLAB命令行窗口输入:

>> !magicCreat
Extracting CTF archive. This may take a few seconds, depending on the 
 size of your application. Please wait... 
...CTF archive extraction complete.
y = 
 
    17    24     1     8    15 
    23     5     7    14    16 
     4     6    13    20    22 
    10    12    19    21     3 
    11    18    25     2     9

程序正常运行,由于命令行输入变量个数小于2,因此M文件输入参数默认值为5,程序产生一个5阶的魔方阵,如果需要输入第2个输入参数,则可以按照以下方式在MATLAB命令行窗口中输入:

>> !magicCreat 3        %创建一个3阶的魔方阵
 
y = 
 
     8     1     6 
     3     5     7 
     4     9     2

16.5.3 Visual C++中创建MAT文件

在16.3节MAT数据文件一节中,介绍了MAT数据文件的基本概念,如何编写MEX文件写入和读出MAT数据文件。在Visual C++开发环境中,同样可以利用API函数库的MAT函数库,写入和读出MAT数据文件。通过这种数据文件的读写,可以有效地实现Visual C++环境同MATLAB开发环境的数据通信接口。

以下matCreatCDemo.c文件为在Visual C++环境下实现MAT数据文件的读写操作,程序代码如下:

/*
 *  matCreatCDemo.c
*/
#include <stdio.h>  
#include <string.h>
#include <stdlib.h>
#include "mat.h"
int main()
{
    //MATFile文件定义,mxArray变量定义
    const char *filename = "MatDemo.mat";
    MATFile *file;
    int flag1,flag2,flag3;
    mxArray *pString, *pArray1, *pArray2;
   // 初始数据定义
    double a1[] = {0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0};
    double a2[] = {9.0, 4.0,5.4,6.4,3.2,1.5};
    // 创建MAT文件
    printf("Creating file %s...\n\n",filename);
    file = matOpen(filename,"w");
    if ( file == NULL )
    {
        printf("ERROR: Can not create file %s\n", filename);
        return(EXIT_FAILURE);
    }
    // 创建字符串mxArray数据结构变量
    pString = mxCreateString("This is the MAT demo in C lanuage! Enojy it~!");
    if (pString == NULL)
    {
        printf("ERROR: Unable to create string!");
        return(EXIT_FAILURE);
    }
    //创建矩阵mxArray数据结构变量
    pArray1 = mxCreateDoubleMatrix(3,3,mxREAL);
    pArray2 = mxCreateDoubleMatrix(2,3,mxREAL);
    if( (pArray1 == NULL)||(pArray2 ==NULL) )
    {
        printf("Error: Cannot create the double matrix!");
        return(EXIT_FAILURE);
    }
    // 将初始数据拷贝给mxArray数据结构变量
    memcpy( (void *)(mxGetPr(pArray1)), (void *)a1, sizeof(a1));
    memcpy( (void *)(mxGetPr(pArray2)), (void *)a2, sizeof(a2));
    // 向MAT文件中写入变量
    flag1 = matPutVariable(file, "variableString", pString);
    flag2 = matPutVariable(file, "variableDoubleMatrix1", pArray1);
    flag3 = matPutVariable(file, "variableDoubleMatrix2", pArray2);
    if(( flag1 != 0)||(flag2 != 0)||(flag3 != 0))
    {
        printf("Can not write variable into the file %s \n", filename);
        return(EXIT_FAILURE);
    }
    // 释放内存空间
    mxDestroyArray(pString);
    mxDestroyArray(pArray1);
    mxDestroyArray(pArray2);
    // 关闭MAT文件
    if(matClose(file) != 0)
    {
        printf("ERROR: Can not close %s file.\n",filename);
        return(EXIT_FAILURE);
    }
  // 重新打开MAT文件
  file = matOpen(filename, "r");
  if (file == NULL) 
  {
    printf("ERROR: Can not open file %s\n", filename);
    return(EXIT_FAILURE);
  }
        //  读取MAT文件的数据变量
  pArray1 = matGetVariable(file, "variableDoubleMatrix1");
  pArray2 = matGetVariable(file, "variableDoubleMatrix2");
  pString = matGetVariable(file, "variableString");
  if ( (pArray1 == NULL) || (pArray2 == NULL) ||(pString == NULL))
  {
    printf("ERROR: Can not reading variables from file %s\n",filename);
    return(EXIT_FAILURE);
  }
  // 释放内存空间
  mxDestroyArray(pArray1);
  mxDestroyArray(pArray2);
  mxDestroyArray(pString);
  // 关闭MAT文件
  if (matClose(file) != 0)
  {
    printf("ERROR: Can not close file %s\n",filename);
    return(EXIT_FAILURE);
  }
      
  printf("Complete!\n");
  return(EXIT_SUCCESS);
}

在Visual C++环境新建一个Win32 Consol Application工程,命名为MatCreatCDemo,Visual C++环境的设置参考16.4.1节的设置。输入以上程序段后,编译运行,程序结果如图16.7所示:

图16.7.Visual C++环境下MAT文件运行结果png

在MatCreatCDemo工程目录下,可以看到新建立的MatDemo.mat文件,将工程目录下的MatDemo.mat文件拷贝到MATLAB的工作路径下,使用load命令可以查看MatDemo文件中的数据,在MATLAB命令行窗口中输入:

>> load MatDemo
>> whos
  Name                        Size                    Bytes  Class

  variableDoubleMatrix1       3x3                        72  double array
  variableDoubleMatrix2       2x3                        48  double array (global)
  variableString              1x43                       86  char array

Grand total is 58 elements using 206 bytes

作者:德特数据
联系方式:156204968@qq.com

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容