我是靠谱客的博主 漂亮野狼,最近开发中收集的这篇文章主要介绍Matab与C混合编程 C_MEX函数编写,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1、为什么我们要用C_MEX 文件

   我们知道Matlab擅长处理矩阵运算,提供了很多内建函数以及工具箱,但是对于大量循环的处理效率较低,会出现计算速度的瓶颈,而C对于循环有着高效的处理方式。结合两者特性,我们尝试将耗时的部分改用C实现,由Matalb进行调用。通过使用mex文件,使得Matlab调用C程序与调用内置函数一样简单。

2.、mex文件的组成

C语言MEX 函数主要由计算子程序和接口子程序两个部分组成。

>CMatlab之间的接口函数(由mexFunction实现)

>用C编写的实现特定功能的计算程序(由用户编写完成特定的功能)

>与平台相关的预处理宏(Windows平台下与C相关的宏,主要与mxArray类相关)

注: 将C/Cpp 文件编译为matlab可以执行的程序,关键是“数据格式的转换”。Matlab中使用的是矩阵类型,一个标量也是使用矩阵进行表述的;而C/CPP中使用的初级类型是int,double等。如何将两类数据调整一致是一个基本问题。

   mex文件入口函数:void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[]);

mexFunction四个参数的意思为:

nlhs= 1,说明调用语句左手面(lhs-lefthand side)有一个变量,即a。

nrhs= 2,说明调用语句右手面(rhs-righthand side)有两个自变量,即b和c。

plhs是一个数组,其内容为指针,该指针指向数据类型mxArray。因为现在左手面只有一个变量,即该数组只有一个指针,plhs[0]指向的结果会赋值给a。

prhs和plhs类似,因为右手面有两个自变量,即该数组有两个指针,prhs[0]指向了b,prhs[1]指向了c。要注意prhs是const的指针数组,即不能改变其指向内容。

注:因为Matlab最基本的单元为array,无论是什么类型也好,如有double array、 cell array、 struct array……所以a,b,c都是array,b= 1.1便是一个1x1的doublearray。而在C语言中,Matlab的array使用mxArray类型来表示。所以就不难明白为什么plhs和prhs都是指向mxArray类型的指针数组。


接下来是在mex文件中实现函数功能,mex文件名就是被Matlab调用的文件名,在C/C++文件中对定义功能,并且接口的数据结构严格依照Matlab的规定,传入传出参数都是mxArray。
(i)先将传入的mxArray参数,利用Matlab提供的API函数转成C/C++数据,如 int mrow = mxGetM(mxArray* p) , double* p = mxGetPr(prhs[0]).
(ii)在mexFunction中调用C/C++function ,得到C/C++中类型数据。
(ii)将得到的C/C++数据转成mxArray数据结构传出。
mex编译器负责将这样的“八股文”翻译成为matlab可以执行的二进制文件。

3、mex文件的编写、编译、运行

注:同一目录下如果有m函数文件和编译生成的mex64库文件,Matlab优先调用库文件函数。
这里我们实现两个双精度数相加,matlab m文件对应函数如下 :
function [ z ] =  mexAdd( x,y )
%UNTITLED Summary of this function goes here
%   Detailed explanation goes here
    disp('this is a function.');
    z = x+y;

end

现在,我们要用C的方式来实现:
mexAdd.c文件如下:
//包含头文件
#include "mex.h"
//C 函数
double mexAdd(double x,double y){
    return x+y;
}
//MEX文件的入口函数mexFunction
void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[]){
    double a;
    double b;
    double *c;
    //输入参数、输出参数判断
    if(nlhs != 1){
        mexErrMsgTxt("One output required!");
    }
    if(nrhs != 2){
        mexErrMsgTxt("Two input required!");
    }
    //传入的mxArray参数,利用Matlab提供的API函数转成C/C++数据
    a = *( mxGetPr(prhs[0]) );
    b = *( mxGetPr(prhs[1]) );
    
    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
    c = mxGetPr(plhs[0]);
    *c = mexAdd(a,b);
}
对于没有配置编译Cmex的首先需要选择配置编译器,如下:
有些matlab 自带有Lcc编译器,只是用lcc编译时不支持汉语注释吗,只能用英语注释。。。



然后就是使用mex命令编译C文件了,编译成功后生成对应的  .mexw64文件或者.mexw32文件,调用时跟普通内建函数使用无区别。


4、数组相加实例

# include "mex.h"
void mexArrayAdd(const int Row,const int Col,const double *A,const double *B,double *C){
    int i,j;
    for(i=0;i<Row;i++){
        for(j=0;j<Col;j++){
            //注意数据的表达方式, C语言是按行存储A[i*Col+j],matlab是按列存储 A[i+j*Row]
            C[i+j*Row] = A[i+j*Row] + B[i+j*Row]; 
        }
    }
}

void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]){
    double *A,*B,*C;
    int RowA,ColA,RowB,ColB;
    if(nlhs != 1){
       mexErrMsgTxt("One output required.");
    }
    else if(nrhs > 2){
        mexErrMsgTxt("Two input required.");
    }
    if( !mxIsDouble(prhs[0]) || !mxIsDouble(prhs[1]) || mxIsComplex(prhs[0]) || mxIsComplex(prhs[1]) ){
        mexErrMsgTxt("Input Array must be double.");
    }
    //获得矩阵的行数
    RowA = mxGetM(prhs[0]);
    //获得矩阵的列数
    ColA = mxGetN(prhs[0]);
    RowB = mxGetM(prhs[1]);
    ColB=  mxGetN(prhs[1]);
    //判断行列是否相等
    if(RowA != RowB || ColA != ColB){
        mexErrMsgTxt("Rows and Cols must be same.");
    }
    //获取指向输入参数的指针
    A = mxGetPr(prhs[0]);
    B = mxGetPr(prhs[1]);
    //生成输出参量的mxArray
    plhs[0] = mxCreateDoubleMatrix(RowA,ColB,mxREAL);
    //获取指向输出参数的指针
    C= mxGetPr(plhs[0]);
    mexArrayAdd(RowA, ColA, A, B, C);
}




最后

以上就是漂亮野狼为你收集整理的Matab与C混合编程 C_MEX函数编写的全部内容,希望文章能够帮你解决Matab与C混合编程 C_MEX函数编写所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部