zoukankan      html  css  js  c++  java
  • 【Matlab开发】MATLAB编译C/C++代码

    在使用MATLAB编译C/C++代码时,C/C++代码中要使用一个mexFunction函数,那么这个函数是如何定义,在编译时又是如何实现的呢?下面我将使用实例进行说明。

       如一个简单的函数:

    double add(double x, double y)

    {

        return x + y;

     }

              mexFunction的定义为:

     void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])

     {

     

      }

    可以看到,mexFunction是没返回值的,它不是通过返回值把结果传回Matlab的,而是通过对参数plhs的赋值。mexFunction的四个参数皆是说明Matlab调用MEX文件时的具体信息,如这样调用函数时:

    >> b = 1.1; c = 2.2;

    >> a = add(b, c)

    mexFunction四个参数的意思为:

    nlhs = 1,说明调用语句左手面(lhsleft hand side)有一个变量,即a

    nrhs = 2,说明调用语句右手面(rhsright hand side)有两个自变量,即bc

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

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

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

     完整的add.c如下:

    #include "mex.h" //使用MEX文件必须包含的头文件

    //执行具体工作的C函数

    double add(double x, double y)

    {

        return x + y;

    }

    // MEX文件接口函数

    void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])

    {

        double *a;

        double b, c;

        plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);

        a = mxGetPr(plhs[0]);

        b = *(mxGetPr(prhs[0]));

        c = *(mxGetPr(prhs[1]));

        *a = add(b, c);

    }

     mexFunction的内容是什么意思呢?我们知道,如果这样调用函数时:

    >> output = add(1.1, 2.2);

    在未涉及具体的计算时,output的值是未知的,是未赋值的。所以在具体的程序中,我们建立一个1x1的实double矩阵(使用 mxCreateDoubleMatrix函数,其返回指向刚建立的mxArray的指针),然后令plhs[0]指向它。接着令指针a指向plhs [0]所指向的mxArray的第一个元素(使用mxGetPr函数,返回指向mxArray的首元素的指针)。同样地,我们把prhs[0]prhs [1]所指向的元素(即1.12.2)取出来赋给bc。于是我们可以把bc作自变量传给函数add,得出给果赋给指针a所指向的mxArray中的元素。因为a是指向plhs[0]所指向的mxArray的元素,所以最后作输出时,plhs[0]所指向的mxArray赋值给output,则 output便是已计算好的结果了。

    实际上mexFunction是没有这么简单的,我们要对用户的输入自变量的个数和类型进行测试,以确保输入正确。如在add函数的例子中,用户输入char array便是一种错误了。

    从上面的讲述中我们总结出,MEX文件实现了一种接口,把C语言中的计算结果适当地返回给Matlab罢了。当我们已经有用C编写的大型程序时,大可不必在 Matlab里重写,只写个接口,做成MEX文件就成了。另外,在Matlab程序中的部份计算瓶颈(如循环),可通过MEX文件用C语言实现,以提高计算速度。

     

       

    一个简单的MEX文件例子:m文件建立一个1000×1000Hilbert矩阵。

     

    % mextest.m

    tic

    m=1000;

    n=1000;

    a=zeros(m,n);

    for i=1:1000

         for j=1:1000

             a(i,j)=1/(i+j);

         end

    end

    toc

     

     matlab中新建一个Matlab_1.cpp 文件并输入以下程序:

     #include "mex.h"

     

     

    void hilb(double *y,int n)

    {

        int i,j;

        for(i=0;i<n;i++)

            for(j=0;j<n;j++)

                *(y+j+i*n)=1/((double)i+(double)j+1);

    }

     

     

    void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])

    {

        double x,*y;

        int n;

     

        if (nrhs!=1)

            mexErrMsgTxt("One inputs required.");

        if (nlhs != 1)

            mexErrMsgTxt("One output required.");

        if (!mxIsDouble(prhs[0])||mxGetN(prhs[0])*mxGetM(prhs[0])!=1)

            mexErrMsgTxt("Input must be scalars.");

        x=mxGetScalar(prhs[0]);

        plhs[0]=mxCreateDoubleMatrix(x,x,mxREAL);

        n=mxGetM(plhs[0]);

        y=mxGetPr(plhs[0]);

        hilb(y,n);

    }

     该程序是一个C语言程序,它也实现了建立Hilbert矩阵的功能。在MATLAB命令窗口输入以下命令:mex Matlab_1.cpp,即可编译成功。进入该文件夹,会发现多了一个文件:Matlab_1.mexw32,其中Matlab_1.mexw32即是MEX文件。运行下面程序:

     

    tic

    a=Matlab_1(1000);

    toc

    由上面实验看出,同样功能的MEX文件比m文件快得多。

           MEX文件的组成与参数

    MEX文件的源代码一般由两部分组成:

    (1)计算过程。该过程包含了MEX文件实现计算功能的代码,是标准的C语言子程序。

    (2)入口过程。该过程提供计算过程与MATLAB之间的接口,以入口函数mxFunction实现。在该过程中,通常所做的工作是检测输入、输出参数个数和类型的正确性,然后利用mx-函数得到MATLAB传递过来的变量(比如矩阵的维数、向量的地址等),传递给计算过程。

    MEX文件的计算过程和入口过程也可以合并在一起。但不管那种情况,都要包含#include "mex.h",以保证入口点和接口过程的正确声明。注意,入口过程的名称必须是mexFunction,并且包含四个参数,即:

    void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])

    其中,参数nlhsnrhs表示MATLAB在调用该MEX文件时等式左端和右端变量的个数,例如在MATLAB命令窗口中输入以下命令:

    [a,b,c]=Matlab_1(d,e,f,g)

    nlhs3nrhs4

    MATLAB在调用MEX文件时,输入和输出参数保存在两个mxArray*类型的指针数组中,分别为prhs[]plhs[]prhs[0]表示第一个输入参数,prhs[1]表示第二个输入参数,,以此类推。如上例中,d→prhs[0]e→prhs[1]f→prhs[2]f→prhs[3]。同时注意,这些参数的类型都是mxArray *

    接口过程要把参数传递给计算过程,还需要从prhs中读出矩阵的信息,这就要用到下面的mx-函数和mex-函数。

  • 相关阅读:
    mac os programming
    Rejecting Good Engineers?
    Do Undergrads in MIT Struggle to Obtain Good Grades?
    Go to industry?
    LaTex Tricks
    Convert jupyter notebooks to python files
    How to get gradients with respect to the inputs in pytorch
    Uninstall cuda 9.1 and install cuda 8.0
    How to edit codes on the server which runs jupyter notebook using your pc's bwroser
    Leetcode No.94 Binary Tree Inorder Traversal二叉树中序遍历(c++实现)
  • 原文地址:https://www.cnblogs.com/huty/p/8518789.html
Copyright © 2011-2022 走看看