【VC++开源代码栏目提醒】:文章导读:在新的一年中,各位网友都进入紧张的学习或是工作阶段。
网学会员整理了VC++开源代码-matlab中调用C代码 - 综合课件的相关内容供大家参考,祝大家在新的一年里工作和学习顺利!
如果我有一个用C语言写的函数实现了一个功能如一个简单的函数 double adddouble x double y return x y 现在我想要在Matlab中使用它比如输入 gtgt a add1.1 2.2 3.3000 要得出以上的结果那应该怎样做呢 解决方法之一是要通过使用MEX文件MEX文件使得调用C函数和调用Matlab的内置函数一样方便。
MEX文件是由原C
代码加上MEX文件专用的接口函数后编译而成的。
可以这样理解MEX文件实现了一种接口它把在Matlab中调用函数时输入的自变量通过特定的接口调入了C函数得出的结果再通过该接口调回Matlab。
该特定接口的操作包含在mexFunction这个函数中由使用者具体设定。
所以现在我们要写一个包含add和mexFunction的C文件Matlab调用函数把函数中的自变量如上例中的1.1和2.2传给 mexFunction的一个参数mexFunction把该值传给add把得出的结果传回给mexFunction的另一个参数Matlab通过该参数来给出在Matlab语句中调用函数时的输出值如上例中的a。
值得注意的是mex文件是与平台有关的以我的理解mex文件就是另类的动态链接库。
在matlab6.5中使用mex -v 选项你可以看到最后mex阶段有类似如下的信息 --gt quotdel _lib94902.objquot --gt quotdel quottest.expquotquot --gt quotdel quottest.libquotquot 也就是说虽然在matlab6.5生成的是dll文件但是中间确实有过lib文件生成。
比如该C文件已写好名为add.c。
那么在Matlab中输入 gtgt mex add.c 就能把add.c编译为MEX文件编译器的设置使用指令mex -setup在Windows中MEX文件类型为mexw32即现在我们得出add.mexw32文件。
现在我们就可以像调用M函数那样调用 MEX文件如上面说到的例子。
所以通过MEX文件使用C函数就和使用M函数是一样的了。
我们现在来说mexFunction怎样写。
mexFunction的定义为 void mexFunctionint nlhs mxArray plhs int nrhs const mxArray prhs 可以看到mexFunction是没返回值的它不是通过返回值把结果传回Matlab的而是通过对参数plhs的赋值。
mexFunction的四个参数皆是说明Matlab调用MEX文件时的具体信息如这样调用函数时 gtgt b 1.1 c 2.2 gtgt a addb c mexFunction四个参数的意思为 nlhs 1说明调用语句左手面lhsleft hand side有一个变量即a。
nrhs 2说明调用语句右手面rhsright hand side有两个自变量即b和c。
plhs是一个数组其内容为指针该指针指向数据类型mxArray。
因为现在左手面只有一个变量即该数组只有一个指针plhs0指向的结果会赋值给a。
prhs和plhs类似因为右手面有两个自变量即该数组有两个指针prhs0指向了bprhs1指向了c。
要注意prhs是const的指针数组即不能改变其指向内容。
因为Matlab最基本的单元为array无论是什么类型也好如有double array、 cell array、 struct array……所以abc都是arrayb 1.1便是一个1x1的double array。
而在C语言中Matlab的array使用mxArray类型来表示。
所以就不难明白为什么plhs和prhs都是指向mxArray类型的指针数组。
完整的add.c如下 include quotmex.hquot // 使用MEX文件必须包含的头文件 // 执行具体工作的C函数 double adddouble x double y return x y // MEX文件接口函数 void mexFunctionint nlhsmxArray plhs int nrhsconst mxArray prhs double a double b c plhs0 mxCreateDoubleMatrix1 1 mxREAL a mxGetPrplhs0 b mxGetPrprhs0 c mxGetPrprhs1 a addb c mexFunction的内容是什么意思呢我们知道如果这样调用函数时 gtgt output add1.1 2.2 在未涉及具体的计算时output的值是未知的是未赋值的。
所以在具体的程序中我们建立一个1x1的实double矩阵使用 mxCreateDoubleMatrix函数其返回指向刚建立的mxArray的指针然后令plhs0指向它。
接着令指针a指向plhs 0所指向的mxArray的第一个元素使用mxGetPr函数返回指向mxArray的首元素的指针。
同样地我们把prhs0和prhs 1所指向的元素即1.1和2.2取出来赋给b和c。
于是我们可以把b和c作自变量传给函数add得出给果赋给指针a所指向的mxArray中的元素。
因为a是指向plhs0所指向的mxArray的元素所以最后作输出时plhs0所指向的mxArray赋值给output则 output便是已计算好的结果了。
上面说的一大堆指向这指向那什么mxArray初学者肯定都会被弄到头晕眼花了。
很抱歉要搞清楚这些乱糟糟的关系只有多看多练。
实际上mexFunction是没有这么简单的我们要对用户的输入自变量的个数和类型进行测试以确保输入正确。
如在add函数的例子中用户输入char array便是一种错误了。
从上面的讲述中我们总结出MEX文件实现了一种接口把C语言中的计算结果适当地返回给Matlab罢了。
当我们已经有用C编写的大型程序时大可不必在 Matlab里重写只写个接口做成MEX文件就成了。
另外在Matlab程序中的部份计算瓶颈如循环可通过MEX文件用C语言实现以提高计算速度。
以上是对mex文件的初步认识下面详细介绍如何用c语言编写mex文件 1 为什么要用C语言编写MEX文件 MATLAB是矩阵语言是为向量和矩阵操作设计的一般来说如果运算可以用向量或矩阵实现其运算速度是非常快的。
但若运算中涉及到大量的循环处理MATLAB的速度的令人难以忍受的。
解决方法之一为当必须使用for循环时把它写为MEX文件这样不必在每次运行循环中的语句时MATLAB都对它们进行解释。
2 编译器的安装与配置 要使用MATLAB编译器用户计算机上应用事先安装与MATLAB适配的以下任何一种ANSI C/C编译器 5.0、6.0版的MicroSoft Visual CMSVC 5.0、5.2、5.3、5.4、5.5版的Borland C LCC由MATLAB自带只能用来产生MEX文件 下面是安装与配置MATLAB编译器应用程序MEX的设置的步骤 1在MATLAB命令窗口中运行mex –setup出现下列提示 Please choose your compiler for building external interface MEX files: Would you like mex to locate installed compilers y/n 2选择yMATLAB将自动搜索计算机上已安装的外部编译器的类型、版本及所在路径并列出来让用户选择 Select a compiler: 1 Borland CBuilder version 6.0 in C:Program FilesBorland 2 Digital Visual Fortran version 6.0 in C:Program FilesMicrosoft Visual Studio 3 Lcc C version 2.4 in D:MATLAB6P5P1syslcc 4 Microsoft Visual C/C version 6.0 in C:Program FilesMicrosoft Visual Studio 0 None Compiler: 3选择其中一种在这里选择了3MATLAB让用户进行确认 Please verify your choices: Compiler: Lcc C 2.4 Location: D:MATLAB6P5P1syslcc Are these correcty/n: 4选择y结束MATLAB编译器的配置。
3 一个简单的MEX文件例子 【例1】用m文件建立一个1000×1000的Hilbert矩阵。
tic m1000 n1000 azerosmn for i1:1000 for j1:1000 aij1/ij end end toc 在matlab中新建一个Matlab_1.cpp 文件并输入以下程序 include quotmex.hquot //计算过程 void hilbdouble yint n int ij fori0iltni forj0jltnj yjin1/doubleidoublej1 //接口过程 void mexFunctionint nlhsmxArray plhsint nrhsconst mxArray prhs double xy int n if nrhs1 mexErrMsgTxtquotOne inputs required.quot if nlhs 1 mexErrMsgTxtquotOne output required.quot if mxIsDoubleprhs0mxGetNprhs0mxGetMprhs01 mexErrMsgTxtquotInput must be scalars.quot xmxGetScalarprhs0 plhs0mxCreateDoubleMatrixxxmxREAL nmxGetMplhs0 ymxGetPrplhs0 hilbyn 该程序是一个C语言程序它也实现了建立Hilbert矩阵的功能。
在MATLAB命令窗口输入以下命令mex Matlab_1.cpp即可编译成功。
进入该文件夹会发现多了两个文件Matlab_1.asv和Matlab_1.dll其中Matlab_1.dll即是MEX文件。
运行下面程序 tic aMatlab_11000 toc elapsed_time 0.0470 由上面看出同样功能的MEX文件比m文件快得多。
4 MEX文件的组成与参数 MEX文件的源
代码一般由两部分组成 1计算过程。
该过程包含了MEX文件实现计算功能的
代码是标准的C语言子程序。
2入口过程。
该过程提供计算过程与MATLAB之间的接口以入口函数mxFunction实现。
在该过程中通常所做的工作是检测输入、输出参数个数和类型的正确性然后利用mx-函数得到MATLAB传递过来的变量比如矩阵的维数、向量的地址等传递给计算过程。
MEX文件的计算过程和入口过程也可以合并在一起。
但不管那种情况都要包含include quotmex.hquot以保证入口点和接口过程的正确声明。
注意入口过程的名称必须是mexFunction并且包含四个参数即 void mexFunctionint nlhsmxArray plhsint nrhsconst mxArray prhs 其中参数nlhs和nrhs表示MATLAB在调用该MEX文件时等式左端和右端变量的个数例如在MATLAB命令窗口中输入以下命令 abcMatlab_1defg 则nlhs为3nrhs为4。
MATLAB在调用MEX文件时输入和输出参数保存在两个mxArray类型的指针数组中分别为prhs和plhs。
prhs0表示第一个输入参数prhs1表示第二个输入参数…以此类推。
如上例中d→prhs0e→prhs1f→prhs2f→prhs3。
同时注意这些参数的类型都是mxArray 。
接口过程要把参数传递给计算过程还需要从prhs中读出矩阵的信息这就要用到下面的mx-函数和mex-函数。
5 常用的mex-函数和mx-函数 在MATLAB6.5版本中提供的mx-函数有106个mex-函数有38个下面我们仅介绍常用的函数。
5.1入口函数mexFunction 该函数是C MEX文件的入口函数它的格式是固定的 void mexFunctionint nlhsmxArray plhsint nrhsconst mxArray prhs 说明MATLAB函数的调用方式一般为abc…被调用函数名称def…nlhs保存了等号左端输出参数的个数指针数组plhs具体保存了等号左端各参数的地址注意在plhs各元素针向的mxArray内存未分配需在接口过程中分配内存prhs保存了等号右端输入参数的个数指针数组prhs具体保存了等号右端各参数的地址注意MATLAB在调用该MEX文件时各输入参数已存在所以在接口过程中不需要再为这些参数分配内存。
5.2出错信息发布函数mexErrMsgTxtmexWarnMsgTxt 两函数的具体格式如下 include quotmex.hquot void mexErrMsgTxtconst char error_msg void mexWarnMsgTxtconst char warning_msg 其中error_msg包含了要显示错误信息warning_msg包含要显示的警告信息。
两函数的区别在于mexErrMsgTxt显示出错信息后即返回到MATLAB而mexWarnMsgTxt显示警告信息后继续执行。
5.3 mexCallMATLAB和mexEvalString 两函数具体格式如下 include quotmex.hquot int mexCallMATLABint nlhs mxArray plhs int nrhs mxArray prhs const char command_name int mexEvalStringconst char command mexCallMATLAB前四个参数的含义与mexFunction的参数相同command_name可以MATLAB内建函数名、用户自定义函数、M文件或MEX文件名构成的字符串也可以MATLAB合法的运算符。
mexEvalString用来操作MATLAB空间已存在的变量它不返回任何参数。
mexCallMATLAB与mexEvalString差异较大请看下面的例子。
【例2】试用MEX文件求5阶完全图邻接矩阵的特征值及对应的特征向量。
下面是求该矩阵的MEX文件。
include quotmex.hquot void mexFunctionint nlhsmxArray plhsint nrhsconst mxArray prhs double x mxArray yzw int n if nrhs1 mexErrMsgTxtquotOne inputs required.quot if nlhs 3 mexErrMsgTxtquotThree output required.quot if mxIsDoubleprhs0mxGetNprhs0mxGetMprhs01 mexErrMsgTxtquotInput must be a scalar.quot xmxGetScalarprhs0 plhs0mxCreateDoubleMatrixxxmxREAL plhs1mxCreateDoubleMatrixxxmxREAL plhs2mxCreateDoubleMatrixxxmxREAL nmxGetMplhs0 yplhs0 zplhs1 wplhs2 //利用mexCallMATLAB计算特征值 mexCallMATLAB1ampplhs11prhsquotonesquot mexCallMATLAB1ampplhs21prhsquoteyequot mexCallMATLAB1ampplhs02ampplhs1quot-quot mexCallMATLAB2ampplhs11ampplhs0quoteigquot //演示mexEvalString的功能 mexEvalStringquotyy2quot mexEvalStringquotaa2quot 在MATLAB命令窗口输入以下命令 gtgt mex Matlab_2.cpp gtgt clear gtgt amagic5 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 gtgt yzwMatlab_25 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 quotmatrix.hquot mxArray mxCreateDoubleMatrixint 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 quotmatrix.hquot int mxGetMconst mxArray array_ptr int mxGetNconst mxArray array_ptr 与之相关的还有 mxSetM设置矩阵的行维 mxSetN设置矩阵的列维 5.6 获取矩阵实部和虚部函数mxGetPr、mxGetPi 其格式如下 include quotmatrix.hquot double mxGetPrconst mxArray array_ptr double mxGetPiconst mxArray array_ptr 与之相关的函数还有 mxSetPr设置矩阵的实部 mxSetPi设置矩阵的虚部 【例3】实现字符串的倒序输出。
include quotmex.hquot void revordchar input_bufint buflenchar output_buf int i //实现字符串倒序 fori0iltbuflen-1i output_bufiinput_bufbuflen-i-2 void mexFunctionint nlhsmxArray plhsint nrhsconst mxArray prhs //定义输入和输出参量的指针 char input_bufoutput_buf int buflenstatus //检查输入参数个数 ifnrhs1 mexErrMsgTxtquotOne input required.quot else ifnlhsgt1 mexErrMsgTxtquotToo many output arguments.quot //检查输入参数是否是一个字符串 ifmxIsCharprhs01 mexErrMsgTxtquotInput must be a string.quot //检查输入参数是否是一个行变量 ifmxGetMprhs01 mexErrMsgTxtquotInput must a row vector.quot //得到输入字符串的长度 buflenmxGetMprhs0mxGetNprhs01 //为输入和输出字符串分配内存 input_bufmxCallocbuflensizeofchar output_bufmxCallocbuflensizeofchar //将输入参量的mxArray结构中的数值拷贝到C类型字符串指针 statusmxGetStringprhs0input_bufbuflen ifstatus0 mexWarnMsgTxtquotNot enough space. String is truncated.quot //调用C程序 revordinput_bufbuflenoutput_buf plhs0mxCreateStringoutput_buf 这个程序中需要注意的地方是mxCalloc函数它代替了标准C程序中的calloc函数用于动态分配内存而mxCalloc函数采用的是MATLAB的内存管理机制并将所有申请的内存初始化为0因此凡是C
代码需要使用calloc函数的地方对应的Mex文件应该使用mxCalloc函数。
同样凡是C
代码需要使用realloc函数的地方对应的Mex文件应该使用mxRealloc函数。
在MATLAB命令窗口中对revord.cpp程序
代码编译链接 gtgt mex revord.cpp 在MATLAB命令窗口中对C-MEX文件revord.dll进行测试 gtgt xI am student. gtgt revordx ans .tneduts ma I Re:【求助】怎么样实现把C
代码在matlab中调用并且编译链接运行 这里有一个例子程序比较简单按照这种格式可以把c函数编译成matlab可以调用的dll文件要链接的头文件有matrix.hmex.htmwtypes.h在
vc环境中可以找到这些文件 //------------------------------------------------------------------------------------------------- include quotmex.hquot / timestwo.c - example found in API guide Computational function that takes a scalar and double it. This is a MEX-file for MATLAB. Copyright 1984-2000 The MathWorks Inc. / / Revision: 1.8 / void timestwodouble y double x//用户的c函数 y0 2.0x0 //下面这个mexFunction的目的是使MATLAB知道如何调用这个timestwo函数 void mexFunction int nlhs mxArray plhs int nrhs const mxArray prhs //nlhs是MATLAB命令行方式下输出参数的个数 //plhs是MATLAB命令行方式下输出参数 //nrhs是MATLAB命令行方式下输入参数的个数 //prhs是MATLAB命令行方式下输入参数 double xy int mrowsncols / Check for proper number of arguments. / ifnrhs1 mexErrMsgTxtquotOne input required.quot else ifnlhsgt1 mexErrMsgTxtquotToo many output argumentsquot /在MATLAB命令行方式下本MEX文件的调用格式是ytimestwox输入参数x个数1 输出参数y个数为1所以在本程序开始时就检查nrhs是否为1及n.
上一篇:
C++ 小型股票交易系统的设计及代码 pdf
下一篇:
4种小菜缓解孕妈咪不适