Matlab2014b与C/C++(VS2013)混合编程

Refer from http://blog.csdn.net/langb2014/article/details/48375117


很多精通单一语言,c语言或matlab的人,在处理经常遇到Matlab与C/C++混合编程的问题,而且都会出现各种编译问题,使得这两种语言之间产生了代沟,因为我对这些问题也比较反感,因此做一个简单认识和学习。

一、Matlab调用C/C++

Matlab调用C/C++的方式主要有两种:利用MEX技术和调用C/C++动态连接库。

利用MEX技术:

MEX是Matlab Executable的缩写。一个C/C++的MEX源程序通常包括4个组成部分,其中前3个是必须包含的内容,第4个则根据所实现的功能灵活选用:(1)#include “mex.h”;(2)MEX文件的入口函数mexFunction, MEX文件导出名必须为mexFunction函数;(3)mxArray;(4)API函数

mexFunction函数中的四个参数说明:

    nlhs:mexFunction的第一个参数,它指示Matlab的调用命令中等号左侧有几个变量。

    plhs: mexFunction的第二个参数,它指示Matlab的调用命令中等号左侧变量的指针。

    nrhs:mexFunction的第三个参数,它指示Matlab的调用命令中等号右侧的变量个数。

    prhs:mexFunction的第四个参数,它指示Matlab调用命令中等号右侧的变量指针。

  通过简单的例子说明C/C++的MEX源程序编写和调用过程:

[cpp]  view plain  copy
  1. #include "mex.h"   
  2. /*  
  3. * timestwo.c - example found in API guide  
  4.  
  5. * Computational function that takes a scalar and doubles it.  
  6.  
  7. * This is a MEX-file for MATLAB.  
  8. * Copyright (c) 1984-1998 The MathWorks, Inc.  
  9. */   
  10. /* $Revision: 1.5 $ */   
  11. /* 本MEX文件的目的是实现timestwo的功能  
  12.  void timestwo(double y[], double x[])是你的C++函数 */   
  13. void timestwo(double y[], double x[])   
  14. {   
  15. y[0] = 2.0*x[0];   
  16. }   
  17.     
  18. /*下面这个mexFunction的目的是使MATLAB知道如何调用这个timestwo函数*/   
  19. void mexFunction( int nlhs, mxArray *plhs[],   
  20. int nrhs, const mxArray *prhs[] )   
  21.     
  22. /* nlhs是MATLAB命令行方式下输出参数的个数;  
  23.  *plhs[]是MATLAB命令行方式下的输出参数;  
  24.  nrhs是MATLAB命令行方式下输入参数的个数;  
  25.  *prhs[]是MATLAB命令行方式下的输入参数; */   
  26.     
  27. {   
  28. double *x,*y;   
  29. int mrows,ncols;   
  30. /* Check for proper number of arguments. */   
  31. if(nrhs!=1) {   
  32. mexErrMsgTxt("One input required.");   
  33. else if(nlhs>1) {   
  34. mexErrMsgTxt("Too many output arguments");   
  35. }   
  36.     
  37. /* 在MATLAB命令行方式下,本MEX文件的调用格式是y=timestwo(x)  
  38.  输入参数(x)个数=1,输出参数(y)个数=1,所以在程序一  
  39.  开始就检查nrhs是否=1以及nlhs是否>1(因为MATLAB有一个缺省  
  40.  输出参数ans,所以nlhs可以=0 */   
  41.  输出参数ans,所以nlhs可以=0 */   
  42. /* The input must be a noncomplex scalar double.*/   
  43.     
  44. mrows = mxGetM(prhs[0]); /* 获得输入矩阵的行数 */   
  45. ncols = mxGetN(prhs[0]); /* 获得输入矩阵的列数 */   
  46. if( !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) ||   
  47. !(mrows==1 && ncols==1) ) {   
  48. mexErrMsgTxt("Input must be a noncomplex scalar double.");   
  49. /* 判断输入矩阵是否是double类,以及它是否只包括单个元素 */   
  50.     
  51. /* 为输出创佳一个矩阵,显然这个矩阵也应该是1x1的 */   
  52. plhs[0] = mxCreateDoubleMatrix(mrows,ncols, mxREAL);   
  53. /* 获得指向输入/输出矩阵数据的指针 */   
  54. x = mxGetPr(prhs[0]);   
  55. y = mxGetPr(plhs[0]);   
  56. /* 调用C++函数timestwo(y,x) */   
  57. timestwo(y,x);   
  58. }   

可在matlab中编译,也可以直接在C++环境中编译: 

1).(在matlab中)用指令mex  timestwo.c编译此文件,然后在MATLAB命令行下调用生成的MEX文件即可。2). (在VS2013中)和一般c++一样编译后,就会产生dll,这样可以直接在Matlab中用了,或者copy且更改后缀名.mexw32即可。

MEX文件的编程规则
     (1)编制自己的C++算法程序 
     (2)紧跟着定义mexFunction函数,mexFunction的定义法唯一: 
    它只能是如下形式: 
     void mexFunction( int nlhs, mxArray *plhs[], 
     int nrhs, const mxArray *prhs[] ) 
    其名称和参数类型不许有任何改变,在mexFunciton函数中可以调用你刚定义好的C++程序。 
MEX文件的编译 
    MATLAB提供了专门编译MEX文件的工具:mex,它可以把你做好的C++源程序编译成 .mex文件供MATLAB在命令行方式下调用。调用时输入你的C++函数名(上例中为timestwo)。具体mex的设置和使用方法可以在MATLAB命令行方式下用help mex命令获得。

调用C/C++动态连接库(即:一般普通的C程序dll没有用mex的接口函数)

Matlab提供对动态连接库DLL文件的接口。利用该接口,可在Matlab中调用动态连接库导出的函数。Matlab对DLL的接口支持各种语言编写的DLL文件。在调用DLL文件之前,需要准备函数定义的头文件。对于C/C++语言开发的DLL文件,可使用源程序中相应的头文件;而对于其他语言开发的DLL,则要手工准备等效的C语言函数定义头文件。

  在Matlab中利用动态连接库接口技术通常需要完成以下4个步骤:

  (1)打开动态连接库文件;(2)为调用函数准备数据;(3)调用动态连接库文件中导出的函数;(4)关闭动态连接库文件。

  为了实现以上步骤,用到的Matlab函数有:loadlibrary, loadlibrary, calllib, libfunctions, lipointer, libstruct, libisloaded。

下面举例说明Matlab调用C/C++动态连接库的方法和步骤:

  a.在VS环境下,新建工程->win32动态连接库->工程名Test->empty工程->完成;

  b.新建->C++源文件->添加a.cpp,内容为:#include "a.h"

  _declspec(dllexport) int  add(int a,  int b)  { return a+b; }

  c.新建->C/C++头文件->添加a.h,内容为: _declspec(dllexport)  int  add(int a,intb); 然后编译生成Test.dll动态连接库文件,将Test.dll和a.h拷到Matlab 工作目录下。

  d.在Matlab命令行下,调用Test.dll:>>loadlibrary(‘Test’,’a.h’);  >>x=7;

  >>y=8;  >>calllib(‘Test’,‘add’,x,y);  Ans=15  >>unloadlibrary(‘Test’).

  调用DLL动态连接库的方法,为Matlab重用工程实践中积累的大量实用C/C++代码提供了一种简洁方便的方法。与调用MEX文件相比,该方法更加简便实用。(C++库和函数的重载不知道怎么实现)

二、C/C++调用Matlab

1、设置matlab编译器
在命令行窗口下,输入并执行如下命令:mex –setup
在出现的编译器中,选择VS2013
然后在输入命令:mbuild –setup 同样选择VS2013
2.    编写.m文件

如下函数时完成图像的分割功能,第一个参数是图像的文件名(路径),第二个参数是分割图像阈值的大小;完成分割后,将图像保存为result.bmp;返回值则是原图像的数据;

[cpp]  view plain  copy
  1. function imagedata=improcess(filename,threshold);    
  2. imagedata=double(imread(filename));    
  3. newbuf=imagedata;    
  4. [M N]=size(imagedata);    
  5. for i=1:1:M    
  6.   for j=1:1:N    
  7.       if imagedata(i,j)>threshold    
  8.           newbuf(i,j)=255;    
  9.       else    
  10.           newbuf(i,j)=0;    
  11.       end    
  12.   end    
  13. end    
  14. imwrite(uint8(newbuf),'result.bmp');    
  15. return;   

3、编译.m文件

mcc -W cpplib:MatImprocess -T link:lib improcess
解释:其中-W是控制编译之后的封装格式;
cpplib,是指编译成C++的lib;
cpplib冒号后面是指编译的库的名字;
-T表示目标,link:lib表示要连接到一个库文件的目标,目标的名字即是.m函数的名字。
编译完成之后,MatImprocess.h MatImprocess.lib MatImprocess.dll这三个文件时我们在c++中调用所需要的;这三个文件和我们用c++编写dll时,生成的三个文件时对应的;

但是由于我的matlab是2014b,破解不是很完美,所以这个自带mcc编译器运行不起来,后面暂时做不了了,先隔一段时间再弄一下了


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值