matlabroot、addpath、pwd、mex C++ 编译的时候缺少mex.h文件

 
 
 
 
cd(fullfile(matlabroot, '/help/techdoc/matlab_env/examples'))

cd('C:/Program Files/MATLAB/R2010b/help/techdoc/matlab_env/examples')

cd('C:/Program Files')

>> cd

C:\Program Files

dir_str1= 'E:\F';

dir_str2= 'E:\D';

pwd

ans =

C:\Program Files

>> cd(dir_str2);

pwd

ans =

E:\D

>> cd dir_str1

错误使用 cd

无法将目录改变为 dir_str1 (Name is nonexistent ornot a directory)。

>> cd E:\E

>> pwd

ans =

E:\E

cd..指的是返回到上一级目录

addpath('folderName1','folderName2','folderName3' ...)

mex 的目的

通过C/C++语言编写代码,在Matlab中将其编译成mex文件主要可以做以下几方面的事情:

1、加快程序的执行速度. Matlab在for上如老牛拉车的速度确实让人抓狂.

2、将Matlab作为C++的开发调试环境.尤其是有大量数据需要处理时,用Matlab观察其中间结果十分方便.

3、据称可以弥补Matlab硬件设备接口的薄弱环节.

今天写了第一个使用MEX.

一个简单的对Matlab普通数值矩阵的操作.

其中Matlab规定的与操作系统版本有关的mwSize,mwIndex, size_t在32位系统上其实本质上就是int,所以

一律用int代替.


C++ 编译的时候缺少mex.h文件

该文件在你的matlab安装路径下。例如 我的是: D:\Program Files\MATLAB\R2012b\extern\include

如果你只将mex.h复制粘贴到你的c工程下,依然会报错,因为mex.h中又包含了其他的matlab头文件。
所以最好的办法是将 D:\Program Files\MATLAB\R2012b\extern\include添加进入c工程的外部依赖项。
具体方法:工程---属性---配置属性---c/c++---常规---附加包含目录:加上头文件存放目录。

新建一个CPP文件,命名为cc.cpp

内容:

#include"mex.h"
double add(double x, double y)
{
return x + y;
}
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的定义为:

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,说明调用语句左手面(lhs-left hand side)有一个变量,即a。

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

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

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

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.1和2.2)取出来赋给b和c。于是我们可以把b和c作自变量传给函数add,得出给果赋给指针a所指向的mxArray中的元素。因为a是指向plhs[0]所指向的mxArray的元素,所以最后作输出时,plhs[0]所指向的mxArray赋值给output,则 output便是已计算好的结果了。

然后:在cc.cpp的同一目录下,新建matlab的m文件mex_first.m

内容:>>cd E:\D\ruanjianxiangmu\matlab\matlab_mex

        >>  mex cc.cpp

则结果:>> mex cc.cpp
        使用 'Microsoft Visual C++ 2015 Professional' 编译。

        MEX 已成功完成。

在命令行窗口输入:cc(1.1,2.2)


ans =


    3.3000


一个令我惊艳的回答:


4 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[])

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

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

则nlhs为3,nrhs为4。

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-函数。

5 常用的mex-函数和mx-函数

在MATLAB6.5版本中,提供的mx-函数有106个,mex-函数有38个,下面我们仅介绍常用的函数。

5.1入口函数mexFunction

该函数是C MEX文件的入口函数,它的格式是固定的:

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

说明:MATLAB函数的调用方式一般为:[a,b,c,…]=被调用函数名称(d,e,f,…),nlhs保存了等号左端输出参数的个数,指针数组plhs具体保存了等号左端各参数的地址,注意在plhs各元素针向的mxArray内存未分配,需在接口过程中分配内存;prhs保存了等号右端输入参数的个数,指针数组prhs具体保存了等号右端各参数的地址,注意MATLAB在调用该MEX文件时,各输入参数已存在,所以在接口过程中不需要再为这些参数分配内存。

5.2出错信息发布函数mexErrMsgTxt,mexWarnMsgTxt

两函数的具体格式如下:

#include "mex.h"

void mexErrMsgTxt(const char *error_msg);

void mexWarnMsgTxt(const char *warning_msg);

其中error_msg包含了要显示错误信息,warning_msg包含要显示的警告信息。两函数的区别在于mexErrMsgTxt显示出错信息后即返回到MATLAB,而mexWarnMsgTxt显示警告信息后继续执行。

5.3 mexCallMATLAB和mexEvalString

两函数具体格式如下:

#include "mex.h"

int mexCallMATLAB(int nlhs, mxArray *plhs[],

int nrhs, mxArray *prhs[], const char *command_name);

int mexEvalString(const char *command);

mexCallMATLAB前四个参数的含义与mexFunction的参数相同,command_name可以MATLAB内建函数名、用户自定义函数、M文件或MEX文件名构成的字符串,也可以MATLAB合法的运算符。

mexEvalString用来操作MATLAB空间已存在的变量,它不返回任何参数。

mexCallMATLAB与mexEvalString差异较大,请看下面的例子。

【例2】试用MEX文件求5阶完全图邻接矩阵 的特征值及对应的特征向量。
5阶完全图的邻接矩阵为:(这里找不到图片了,抱歉。不过不会影响您对本文的理解。)

下面是求该矩阵的MEX文件。

[Matlab_2.cpp]

#include "mex.h"

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

{

    double x;

    mxArray *y,*z,*w;

    int n;

    if (nrhs!=1)

        mexErrMsgTxt("One inputs required.");

    if (nlhs != 3)

        mexErrMsgTxt("Three output required.");

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

        mexErrMsgTxt("Input must be a scalar.");

    x=mxGetScalar(prhs[0]);

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

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

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

    n=mxGetM(plhs[0]);

    y=plhs[0];

    z=plhs[1];

    w=plhs[2];

    //利用mexCallMATLAB计算特征值

    mexCallMATLAB(1,&plhs[1],1,prhs,"ones");

    mexCallMATLAB(1,&plhs[2],1,prhs,"eye");

    mexCallMATLAB(1,&plhs[0],2,&plhs[1],"-");

    mexCallMATLAB(2,&plhs[1],1,&plhs[0],"eig");

    //演示mexEvalString的功能

    mexEvalString("y=y*2");

    mexEvalString("a=a*2");

}

 

在MATLAB命令窗口输入以下命令:

>> mex Matlab_2.cpp

>> clear

>> a=magic(5)

a =

     17     24      1      8     15

     23      5      7     14     16

      4      6     13     20     22

     10     12     19     21      3

     11     18     25      2      9

>> [y,z,w]=Matlab_2(5)

??? Undefined function or variable 'y'.

a =

     34     48      2     16     30

     46     10     14     28     32

      8     12     26     40     44

     20     24     38     42      6

     22     36     50      4     18

y =

      0      1      1      1      1

      1      0      1      1      1

      1      1      0      1      1

      1      1      1      0      1

      1      1      1      1      0

z =

     0.8333    -0.1667    -0.1667     0.2236     0.4472

    -0.1667     0.8333    -0.1667     0.2236     0.4472

    -0.1667    -0.1667     0.8333     0.2236     0.4472

    -0.5000    -0.5000    -0.5000     0.2236     0.4472

          0          0          0    -0.8944     0.4472

w =

     -1      0      0      0      0

      0     -1      0      0      0

      0      0     -1      0      0

      0      0      0     -1      0

      0      0      0      0      4

由上面可以看出,K5的特征值为–1和4,其中–1是四重根。MATLAB提供了mexGetVariable、mexPutVariable函数,以实现MEX空间与其它空间交换数据的任务,具体可以参看MATLAB帮助文档。

5.4建立二维双精度矩阵函数mxCreateDoubleMatrix

其格式具体如下:

#include "matrix.h"

mxArray *mxCreateDoubleMatrix(int m, int n, mxComplexity ComplexFlag);

其中m代表行数,n代表列数,ComplexFlag可取值mxREAL 或mxCOMPLEX。如果创建的矩阵需要虚部,选择mxCOMPLEX,否则选用mxREAL。

类似的函数有:

mxCreateCellArray

创建n维元胞mxArray

mxCreateCellMatrix

创建二维元胞mxArray

mxCreateCharArray

创建n维字符串mxArray

mxCreateCharMatrixFromStrings

创建二维字符串mxArray

mxCreateDoubleMatrix

创建二维双精度浮点mxArray

mxCreateDoubleScalar

创建指定值的二维精度浮点mxArray

mxCreateLogicalArray

创建n维逻辑mxArray,初值为false

mxCreateLogicalMatrix

创建二维逻辑mxArray,初值为false

mxCreateLogicalScalar

创建指定值的二维逻辑mxArray

mxCreateNumericArray

创建n维数值mxArray

mxCreateNumericMatrix

创建二维数值mxArray,初值为0

mxCreateScalarDouble

创建指定值的双精度mxArray

MxCreateSparse

创建二维稀疏mxArray

mxCreateSparseLogicalMatrix

创建二维稀疏逻辑mxArray

MxCreateString

创建指定字符串的1 n的串mxArray

mxCreateStructArray

创建n维架构mxArray

mxCreateStructMatrix

创建二维架构mxArray

 

5.5 获取行维和列维函数mxGetM、mxGetN

其格式如下:

#include "matrix.h"

int mxGetM(const mxArray *array_ptr);

int mxGetN(const mxArray *array_ptr);

与之相关的还有:

mxSetM:设置矩阵的行维

mxSetN:设置矩阵的列维

5.6 获取矩阵实部和虚部函数mxGetPr、mxGetPi

其格式如下:

#include "matrix.h"

double *mxGetPr(const mxArray *array_ptr);

double *mxGetPi(const mxArray *array_ptr);

与之相关的函数还有:

mxSetPr:设置矩阵的实部

mxSetPi:设置矩阵的虚部

【例3】实现字符串的倒序输出。

#include "mex.h"

void revord(char *input_buf,int buflen,char *output_buf)

{

    int i;

    //实现字符串倒序

    for(i=0;i

        *(output_buf+i)=*(input_buf+buflen-i-2);

}

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

{

    //定义输入和输出参量的指针

    char *input_buf,*output_buf;

    int buflen,status;

    //检查输入参数个数

    if(nrhs!=1)

        mexErrMsgTxt("One input required.");

    else if(nlhs>1)

        mexErrMsgTxt("Too many output arguments.");

    //检查输入参数是否是一个字符串

    if(mxIsChar(prhs[0])!=1)

        mexErrMsgTxt("Input must be a string.");

    //检查输入参数是否是一个行变量

    if(mxGetM(prhs[0])!=1)

        mexErrMsgTxt("Input must a row vector.");

    //得到输入字符串的长度

    buflen=(mxGetM(prhs[0])*mxGetN(prhs[0]))+1;

    //为输入和输出字符串分配内存

    input_buf=mxCalloc(buflen,sizeof(char));

    output_buf=mxCalloc(buflen,sizeof(char));

    //将输入参量的mxArray结构中的数值拷贝到C类型字符串指针

    status=mxGetString(prhs[0],input_buf,buflen);

    if(status!=0)

        mexWarnMsgTxt("Not enough space. String is truncated.");

    //调用C程序

    revord(input_buf,buflen,output_buf);

    plhs[0]=mxCreateString(output_buf);

}

这个程序中需要注意的地方是mxCalloc函数,它代替了标准C程序中的calloc函数用于动态分配内存,而mxCalloc函数采用的是MATLAB的内存管理机制,并将所有申请的内存初始化为0,因此凡是C代码需要使用calloc函数的地方,对应的Mex文件应该使用mxCalloc函数。同样,凡是C代码需要使用realloc函数的地方,对应的Mex文件应该使用mxRealloc函数。

在MATLAB命令窗口中对revord.cpp程序代码编译链接:

>> mex revord.cpp

在MATLAB命令窗口中对C-MEX文件revord.dll进行测试:

>> x='I am student.';

>> revord(x)

ans =

.tneduts ma I


该文件在你的matlab安装路径下。例如 我的是: D:\Program Files\MATLAB\R2012b\extern\include

如果你只将mex.h复制粘贴到你的c工程下,依然会报错,因为mex.h中又包含了其他的matlab头文件。
所以最好的办法是将 D:\Program Files\MATLAB\R2012b\extern\include添加进入c工程的外部依赖项。
具体方法:工程---属性---配置属性---c/c++---常规---附加包含目录:加上头文件存放目录。

猜你喜欢

转载自blog.csdn.net/weixin_41484240/article/details/80824254
Mex