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



很多精通单一语言,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源程序编写和调用过程:

    #include "mex.h" 
    /* 
    * timestwo.c - example found in API guide 
    * 
    * Computational function that takes a scalar and doubles it. 
    * 
    * This is a MEX-file for MATLAB. 
    * Copyright (c) 1984-1998 The MathWorks, Inc. 
    */ 
    /* $Revision: 1.5 $ */ 
    /* 本MEX文件的目的是实现timestwo的功能 
     void timestwo(double y[], double x[])是你的C++函数 */ 
    void timestwo(double y[], double x[]) 
    { 
    y[0] = 2.0*x[0]; 
    } 
      
    /*下面这个mexFunction的目的是使MATLAB知道如何调用这个timestwo函数*/ 
    void mexFunction( int nlhs, mxArray *plhs[], 
    int nrhs, const mxArray *prhs[] ) 
      
    /* nlhs是MATLAB命令行方式下输出参数的个数; 
     *plhs[]是MATLAB命令行方式下的输出参数; 
     nrhs是MATLAB命令行方式下输入参数的个数; 
     *prhs[]是MATLAB命令行方式下的输入参数; */ 
      
    { 
    double *x,*y; 
    int mrows,ncols; 
    /* Check for proper number of arguments. */ 
    if(nrhs!=1) { 
    mexErrMsgTxt("One input required."); 
    } else if(nlhs>1) { 
    mexErrMsgTxt("Too many output arguments"); 
    } 
      
    /* 在MATLAB命令行方式下,本MEX文件的调用格式是y=timestwo(x) 
     输入参数(x)个数=1,输出参数(y)个数=1,所以在程序一 
     开始就检查nrhs是否=1以及nlhs是否>1(因为MATLAB有一个缺省 
     输出参数ans,所以nlhs可以=0 */ 
     输出参数ans,所以nlhs可以=0 */ 
    /* The input must be a noncomplex scalar double.*/ 
      
    mrows = mxGetM(prhs[0]); /* 获得输入矩阵的行数 */ 
    ncols = mxGetN(prhs[0]); /* 获得输入矩阵的列数 */ 
    if( !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || 
    !(mrows==1 && ncols==1) ) { 
    mexErrMsgTxt("Input must be a noncomplex scalar double."); 
    } /* 判断输入矩阵是否是double类,以及它是否只包括单个元素 */ 
      
    /* 为输出创佳一个矩阵,显然这个矩阵也应该是1x1的 */ 
    plhs[0] = mxCreateDoubleMatrix(mrows,ncols, mxREAL); 
    /* 获得指向输入/输出矩阵数据的指针 */ 
    x = mxGetPr(prhs[0]); 
    y = mxGetPr(plhs[0]); 
    /* 调用C++函数timestwo(y,x) */ 
    timestwo(y,x); 
    } 

可在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;返回值则是原图像的数据;

function imagedata=improcess(filename,threshold);  
imagedata=double(imread(filename));  
newbuf=imagedata;  
[M N]=size(imagedata);  
for i=1:1:M  
  for j=1:1:N  
      if imagedata(i,j)>threshold  
          newbuf(i,j)=255;  
      else  
          newbuf(i,j)=0;  
      end  
  end  
end  
imwrite(uint8(newbuf),'result.bmp');  
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编译器运行不起来,后面暂时做不了了,先隔一段时间再弄一下了,如果哪位热心的朋友能够在matlab2014b下面完美破解mcc,运行的起来,通知我一下,谢谢。






你可能感兴趣的:(Matlab2014b与C/C++(VS2013)混合编程(未完))