关于Matlab的MEX技术 10分钟教会你简单的matlab和C/C++混合编程(mex文件)

本文介绍如何利用Matlab进行C/C++混合编程,通过实例展示如何编写mex文件实现矩阵运算,以及如何将C代码编译成MEX文件在Matlab中调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

10分钟教会你简单的matlab和C/C++混合编程(mex文件)

标签: matlabmexcc++
379人阅读 评论(0) 收藏 举报
本文章已收录于:
分类:

最近要用matlab提取视频的特征,数据量很大,程序跑起来很慢,于是把其中一个模块改为用C语言来实现。我在这里也记录一下自己的一些心得。

我用的编译器是matlab自带的Lcc-win32 C 2.4.1编译器,好处是可以不依赖高级编译器(如VS、GCC),保证程序只要有matlab即可运行;缺点是只能用C写,不能使用C++的库(比如vector、OpenCV)。所以以下这篇文章只适用于针对矩阵、数组(不包括字符串string、元胞cell)的简单的mex文件编写。

用Lcc编译器编写mex文件的几个注意事项:

1、注释不能有中文,否则报错:Specified export _mexFunction is not defined

2、所有变量定义必须在函数最前面完成,变量没有定义完,不可以执行其他操作,否则报错:illegal statement termination


下面是一个计算矩阵a-b的例子,

其中mexFunction是默认函数名,不用修改,因为matlab调用的时候用的是mex的文件名,而不是函数名。

nlhs代表的是输出参数的个数

plhs是一个指针数组,里面的指针指向mxArray类型,每一个指针指向一个输出

nrhs代表的是输入参数的个数

prhs是一个指针数组,里面的指针指向mxArray类型,每一个指针指向一个输入


  1. #include "mex.h"  
  2. #include "matrix.h"  
  3. // b = [1 2;3 4]  
  4. // a = [5 6;7 8]  
  5. // c = mex_func(a(:), b, size(a,1))  % attention ! a is a(:)   
  6. void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])  
  7. {  
  8.   double *data1 = mxGetPr(prhs[0]);  //get pointer of a(is a vector)  
  9.   double *data2 = mxGetPr(prhs[1]);  //get pointer of b(is a matrix)  
  10.     
  11.   int data1_num = mxGetM(prhs[0]);   // get elements num of data1      
  12.   int data1_h = mxGetScalar(prhs[2]);//get height of matrix a  
  13.   int data1_w = data1_num/data1_h;   //calculate the width of matrix a  
  14.   // the step above is no need when dealing with 2D matrix   
  15.   
  16.   int data2_h = mxGetM(prhs[1]);// get rows of data2  
  17.   int data2_w = mxGetN(prhs[1]);// get cols of data2  
  18.            
  19.   int output_h = data1_h;  
  20.   int output_w = data1_w;  
  21.     
  22.   int i,j;  
  23.   double **copy_array;// pointer of mid-data  
  24.   double *y;  
  25.   //end variable defination, all the defination shoule be set at the beginning  
  26.   //******************************************************  
  27.    
  28.   if ((data1_h!=data2_h)||(data1_w!=data2_w)){  
  29.     printf("matrix dim not matched!\n");  
  30.   }  
  31.   //setup mid-data  
  32.   copy_array = (double **)malloc(sizeof(double *) * output_h);  
  33.   for(i=0; i<output_h;i++){  
  34.       copy_array[i] = (double *)malloc(sizeof(double) * output_w);          
  35.   }  
  36.   // calculate matrix a-b  
  37.   for (i=0; i<output_h; i++){    
  38.         for (j=0; j<output_w;j++){  
  39.               copy_array[i][j] = data1[i+j*data1_h] - data2[i+j*data2_h];    
  40.         }  
  41.   }  
  42.   //end calculating  
  43.   //*******************************************************  
  44.   plhs[0] = mxCreateDoubleMatrix(output_h,output_w, mxREAL);  
  45.   y = mxGetPr(plhs[0]);  
  46.   //copy the mid-data to the output pointer  
  47.   for (i=0;i<output_h;i++){  
  48.       for(j=0;j<output_w;j++){  
  49.           *(y+i+j*output_h)=copy_array[i][j];  
  50.       }  
  51.     }  
  52.     
  53. }  
#include "mex.h"
#include "matrix.h"
// b = [1 2;3 4]
// a = [5 6;7 8]
// c = mex_func(a(:), b, size(a,1))  % attention ! a is a(:) 
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
  double *data1 = mxGetPr(prhs[0]);  //get pointer of a(is a vector)
  double *data2 = mxGetPr(prhs[1]);  //get pointer of b(is a matrix)
  
  int data1_num = mxGetM(prhs[0]);   // get elements num of data1    
  int data1_h = mxGetScalar(prhs[2]);//get height of matrix a
  int data1_w = data1_num/data1_h;   //calculate the width of matrix a
  // the step above is no need when dealing with 2D matrix 

  int data2_h = mxGetM(prhs[1]);// get rows of data2
  int data2_w = mxGetN(prhs[1]);// get cols of data2
         
  int output_h = data1_h;
  int output_w = data1_w;
  
  int i,j;
  double **copy_array;// pointer of mid-data
  double *y;
  //end variable defination, all the defination shoule be set at the beginning
  //******************************************************
 
  if ((data1_h!=data2_h)||(data1_w!=data2_w)){
    printf("matrix dim not matched!\n");
  }
  //setup mid-data
  copy_array = (double **)malloc(sizeof(double *) * output_h);
  for(i=0; i<output_h;i++){
      copy_array[i] = (double *)malloc(sizeof(double) * output_w);	      
  }
  // calculate matrix a-b
  for (i=0; i<output_h; i++){  
        for (j=0; j<output_w;j++){
              copy_array[i][j] = data1[i+j*data1_h] - data2[i+j*data2_h];  
        }
  }
  //end calculating
  //*******************************************************
  plhs[0] = mxCreateDoubleMatrix(output_h,output_w, mxREAL);
  y = mxGetPr(plhs[0]);
  //copy the mid-data to the output pointer
  for (i=0;i<output_h;i++){
      for(j=0;j<output_w;j++){
          *(y+i+j*output_h)=copy_array[i][j];
      }
    }
  
}


简单总结一下几个要点:

mex文件的编写可以分为三个步骤,数据传入,数据处理,数据导出

1、传入矩阵用mxGetPr,传入数值用mxGetScalar

2、获取2维矩阵维度用mxGetM,mxGetN,C模块无法同时获得3维矩阵的三个维度,维度需要自己手动传递

此处有误,可以用函数mxGetDimensions: 就是返回一个指针ptr,每一个指针所指向的值是每一个维度的元素个数。例如有矩阵3*2的矩阵,那么*(ptr)为3,*(ptr+1)为2,如果是3维矩阵,只需要访问*(ptr+2)。参考文章中的第四节有详细描述)

3、数据在内存上都是连续的,访问的时候按列的顺序访问

4、数据传出用mxCreateDoubleMatrix,先创建一个double类型的指针用来存放要导出的数据,然后再拷贝到plhs[i]对应的指针上

参考文章matlab和C/C++混合编程--Mex

0
0
 
 


关于Matlab的MEX技术  


2008-03-30 15:13:58|  分类: CAE |  标签: |举报 |字号 订阅


  下载LOFTER 我的照片书  |




MEX文件的功能主要包括三个方面(参见文献[1]),这里主要是将Matlab作为CFortran代码的调试器。以下工作的软件平台为:

l        Microsoft.Visual.Studio.2005.Professional.Edition.DVD

l        Intel.Visual.Fortran.Compiler.Pro.v9.1.032

l        Matlab 7.5.0(R2007b)

Matlab自带的timestwo.c文件为例(C:\Program Files\MATLAB\R2007b\extern\examples\refbook\timestwo.c)说明MEX的工作流程:用户在Matlab命令行(主界面中的Command Window)下输入:

mex timestwo.c

如果编译顺利完成,同文件夹下会出现一个名为“timestwo.mexw32的文件(Matlab版本为R2007b),再在Matlab命令行下输入:

timestwo(5.5)

输出为:

ans=

11

表示这个函数计算结果正确。要注意C文件的文件名必须是算法函数的函数名(这里二者都是timestwo(这一条似乎不必要)。

制作C-MEX文件的具体步骤:

1.      修改原C代码。
原算法函数不需要修改,但需要新增一个名为mexFunction的函数,另外在文件头部增加“#include "mex.h"”。工作量体现在写mexFunction函数上。当用户输入“timestwo(5.5)”时,Matlab首先进入这个函数,这个函数再调用原算法函数,给出答案。因此对用户输入、输出格式是否正确的检验是在该函数中完成的。另外可以看到,原C函数格式是void fun(y,x),但在Matlab中使用时格式是y=fun(x),这说明mexFunction函数对输入、输出格式可以自由定义。详细的写法参见文献[1]4.3节。

2.      Matlab中将C编译为MEX文件(如前文所述)。

3.      使用这个MEX文件(如前文所述)。另外只要这个timestwo.mexw32文件在当前目录下,关闭Matlab后重新启动仍可以直接使用timestwo函数。

如果要编译Fortran文件,先用mex setup将编译器改为Fortran的编译器,然后用同样的方法编译即可。

参考文献:

[1] 杨高波.精通matlab7.0混合编程.电子工业出版社,2006






  评论这张


转发至微博


 


转发至微博


阅读(2063) | 评论(0)
|
MEX 文件的功能主要包括三个方面(参见文献[1]),这里主要是将Matlab作为CFortran代码的调试器。以下工作的软件平台为:

l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Microsoft.Visual.Studio.2005.Professional.Edition.DVD

l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Intel.Visual.Fortran.Compiler.Pro.v9.1.032

l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Matlab 7.5.0(R2007b)

Matlab自带的timestwo.c文件为例(C:\Program Files\MATLAB\R2007b\extern\examples\refbook\timestwo.c)说明MEX的工作流程:用户在Matlab命令行(主界面中的Command Window)下输入:

mex timestwo.c

如果编译顺利完成,同文件夹下会出现一个名为“timestwo.mexw32的文件(Matlab版本为R2007b),再在Matlab命令行下输入:

timestwo(5.5)

输出为:

ans=

11

表示这个函数计算结果正确。要注意C文件的文件名必须是算法函数的函数名(这里二者都是timestwo(这一条似乎不必要)。

制作C-MEX文件的具体步骤:

1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 修改原C代码。
原算法函数不需要修改,但需要新增一个名为mexFunction的函数,另外在文件头部增加“#include "mex.h"”。工作量体现在写mexFunction函数上。当用户输入“timestwo(5.5)”时,Matlab首先进入这个函数,这个函数再调用原算法函数,给出答案。因此对用户输入、输出格式是否正确的检验是在该函数中完成的。另外可以看到,原C函数格式是void fun(y,x),但在Matlab中使用时格式是y=fun(x),这说明mexFunction函数对输入、输出格式可以自由定义。详细的写法参见文献[1]4.3节。

2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Matlab中将C编译为MEX文件(如前文所述)。

3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用这个MEX文件(如前文所述)。另外只要这个timestwo.mexw32文件在当前目录下,关闭Matlab后重新启动仍可以直接使用timestwo函数。

如果要编译Fortran文件,先用mex setup将编译器改为Fortran的编译器,然后用同样的方法编译即可。

参考文献:

[1] 杨高波.精通matlab7.0混合编程.电子工业出版社,2006

" />
推荐 0   转载


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值