Matlab与C/C++联合编程之Matlab以MEX方式调用C/C++代码(四)
利用Matlab与VC++联合编程,既可在C语言程序中打开Matlab引擎,调用Matlab的ToolBox函数和作图函数,也可在Matlab中调用C代码生成的动态链接库文件,用以加快执行速度、缩短开发周期,取得更好的效果。MATLAB与C语言的接口采用称为MEX的动态链接方式进行。MEX文件是由C源程序经过编译生成的MATLAB动态链接子程序,它的作用十分类似于MATLAB的内建函数,可由MATLAB方便地调用。本文主要讲解从Matlab中调用C/C++代码的相关知识。
Matlab调用C/C++的方式主要有两种:利用MEX技术和调用C/C++动态连接库。
利用MEX技术,从MATLAB调用C/C++代码
1)使用者应该在系统中安装MATLAB支持的C/C++编译器。在Matlab与C/C++混合编程之前,必须先对Matlab的编译应用程序mex和编译器mbuild进行正确的设置:
对Matlab编译应用程序mex的设置:mex –setup.
对Matlab编译器mbuild的设置:mbuild –setup.
2)MEX文件的源文件实际上就是一个C语言源文件, MEX的源文件结构由两部分组成:入口子程序和功能子程序。
入口子程序起链接C子程序与MATLAB系统的作用,是实现MATLAB与C混合编程所必须的。格式为:
- #include “mex.h”
- void mexFunction( int nlhs, mxArray *plhs[],
- int nrhs, const mxArray *prhs[] )
- {
- //C语言代码
- }
其中入口子程序函数名必须为mexFunction。其中nlhs (number of left-hand side) 是输出参数的个数,nrhs(number of right-hand side) 是输入参数的个数。prhs[]与plhs[]是指针数组变量,其元素为指向右变量与左变量的指针。在用户程序中可利用上述指针在C与MATLAB中相互传递数据。MEX函数库里的mexFunction()函数,相当于C语言中的main()函数。MEX源文件没有main(),而是以一个mexFunction()代替。
功能子程序用于完成一些特定的计算功能或硬件处理功能,由上述的入口子程序调用。如果必要,该程序可与入口子程序合二为一。
3)MEX源文件的编译
设上述两部分形成的源文件存为MyMEXFun.c。则可在MATLAB环境下使用mex MyMEXFun.c命令进行编译
4)MEX文件的调用格式
[a,b,c...]=MyMEXFun(x,y,z...)
其中,x,y,z...表示函数的输入变量;a,b,c...表示函数的输出变量。
5)MEX文件的调试
下面由一个简单的例子来讲解下MEX文件的调试。
在Matlab当前目录下新建一文件MyMEXFun.c,文件内容为:
- #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,b,*c;
- a=mxGetScalar(prhs[0]);
- b=mxGetScalar(prhs[1]);
- plhs[0]=mxCreateDoubleMatrix(1,1,mxREAL);
- c=mxGetPr(plhs[0]);
- *c=add(a,b);
- }
首先对文件内容进行简单说明:
其中nlhs (number of left-handside) 是输出参数的个数,nrhs (number of right-hand side) 是输入参数的个数。例如对于c=add(a,b),有nlhs=1,hrhs=2。
plhs[]与prhs[]都是指针数组,也就是说它是个数组,每个元素都是一个指针,这些指针指向的东东的类型是mxArray。那什么是mxArray呢?可以把他理解MATLAB中的矩阵,因为MATLAB中所有数据都是以矩阵的形式保存的。
先讲prhs[],就是输入的参数,prhs[0]指向a,prhs[1]指向b,但是注意不能用*(prhs[0])得到a的值。因为 prhs[0]指向的东西的类型是mxArray(参数列表里看出),想把它的值以我们常用的数值形式赋给一个标量(Scalar),得使用 mxGetScalar()函数转化一下:
double a, b;
a = mxGetScalar(prhs[0]);
b = mxGetScalar(prhs[1]);
plhs对应的输出的内容。plhs[0]这个指针指向输出的第一个参数,就是c=add(a, b)中的c了。记住这个c应该是以mxArray的类型出现的,为了得到mxArray类型的输出量,要使用mxCreateDoubleMatrix()函数,它创建一个指向mxArray类型的指针。
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
参数(1, 1, mxREAL)定义了对应c的尺寸类型,MATLAB中c是以1×1的实数矩阵形式报保存的。
而使用mxGetPr()函数可以得到plhs[0]指向的mxArray的第一个double类型的指针。
double *c;
c = mxGetPr(plhs[0]);
最后调用add()函数
*c=add(a,b);
(a) 在Matlab命令窗口输入命令
mex MyMEXFun.c
可以看到在当前目录生成新文件MyMEXFun.mexw32。在命令窗口中输入c=MyMEXFun(3,4)命令,可得到c=7。
(b) 对程序的调试有两种方法,第一种要借助相应语言的开发环境进行调试,只需要把mex 源文件文件在 Matlab 环境下编译的时候加上 debug 选项即可,例如我们编译一个名字为MyMEXFun.c的 mex 源文件,可以在 Matlab 的 command 窗口输入命令mex –g –v MyMEXFun.c即可。
(2) 在windows 环境下的调试方法。
打开VS2010->File->New->Project->VisualC++->MFC->MFC DLL,新建MFC DLL工程,选择DLL类型为Regular DLL with MFC statically linked,工程名为MexDemo。
为工程添加MyMEXFun.c文件,文件内容与上面相同。
打开文件MexDemo.def,在def文件的EXPORTS项添加mexFunction一行。
右键MexDemo->Properties->VC++Directories->Include Directories,添加目录:C:\ProgramFiles (x86)\MATLAB\R2011b\extern\include和目录C:\ProgramFiles (x86)\MATLAB\R2011b\extern\include\win32
右键MexDemo->Properties->VC++Directories->Library Directories,添加目录:C:\Program Files (x86)\MATLAB\R2011b\extern\lib\win32\microsoft
右键MexDemo->Properties->linker->input中增加Additional Dependencies中增加libmx.liblibmex.lib libmat.lib。
右键MexDemo->C/C++->Preprocessor中增加MATLAB_MEX_FILE
在Linker下output中将后缀改为mexw32,即$(OutDir)\$(ProjectName).mexw32
在需要的地方加入#include “stdafx.h”。
用Ctrl+Alt+P附加调试环境到Matlab,在Matlab中将当前目录更改为生成MyMEXFun.mexw32所在目录,在Matlab命令窗口输入函数调用语句,即可开始调试。
调用C/C++动态连接库
Matlab提供对动态连接库DLL文件的接口。利用该接口,可在Matlab中调用动态连接库导出的函数。Matlab对DLL的接口支持各种语言编写的DLL文件。在调用DLL文件之前,需要准备函数定义的头文件。对于C/C++语言开发的DLL文件,可使用源程序中相应的头文件;而对于其他语言开发的DLL,则要手工准备等效的C语言函数定义头文件。
在Matlab中利用动态连接库接口技术通常需要完成以下4个步骤:
(1)打开动态连接库文件;
(2)为调用函数准备数据;
(3)调用动态连接库文件中导出的函数;
(4)关闭动态连接库文件。
为了实现以上步骤,用到的Matlab函数有:loadlibrary, calllib, libfunctions, lipointer, libstruct,libisloaded等。下面举例说明Matlab调用C/C++动态连接库的方法和步骤:
打开VS2010->File->New->Project->VisualC++->MFC->MFC DLL,新建MFC DLL工程,选择DLL类型为Regular DLL with MFC statically linked,工程名为Test1。
为工程添加a.cpp文件,内容为:
- #include "a.h"
- _declspec(dllexport) int add(int a, int b) { return a+b; }
为工程添加a.h文件,内容为:
- _declspec(dllexport) int add(int a,intb);
然后编译生成Test1.dll动态连接库文件,
将Test1.dll和a.h拷到Matlab 工作目录下。
在Matlab命令行下,调用Test.dll:
>>loadlibrary(‘Test1’,’a.h’);
>>x=7;
>>y=8;
>>calllib(‘Test1’,‘add’,x, y);
Ans=15
>>unloadlibrary(‘Test1’).
调用DLL动态连接库的方法,为Matlab重用工程实践中积累的大量实用C/C++代码提供了一种简洁方便的方法。与调用MEX文件相比,该方法更加简便实用。但是这个接口只支持C,不支持C++库和函数的重载,这种情况下,推荐用MEX-file,若实在要用这种方法(调用C/C++动态连接库),则对于C++要做一些更改。
使用mex时的注意事项:
1.MATLAB调用mex接口时,将参数个数及参数指针传入接口子程序,由接口子程序完成指针和调用变量的赋值、输出数据的内存空间分配,接口子程序再将参数指针或经过赋值的变量作为参数传递给C的计算子程序,完成调用过程。调用时应注意指针所指对象的正确性,为处理正确最好做相应的强制类型转换。
2.mex并不便于调试,因此应在C的IDE中用测试集调试后再放入mex文件中。
3.MATLAB中指向二维及高维数组的指针递增方式是按行递增的,而C中是按列递增的,因此计算index时要注意位置。MATLAB矩阵数据的存储顺序是"从上到下,从左到右"。 MATLAB的指标从1开始,C的指标从0开始。
为了mex的正确执行,也是良好编程习惯的要求,需要对输入参数和输出参数进行个数和类型的检查,常用的mex库函数有:
mxGetClassID //获得指针所指变量类型
mxIsNumeric, mxIsCell等,检查指针所指变量是否为符合某种要求的变量类型。更多可查阅帮助。
参数检查过程中可使用mexErrMsgTxt输出错误信息。
mxGetM, mxGetN,获得矩阵的行数和列数
mxGetDimensions,获得矩阵维数
mxGetPr,mxGetPi,获得矩阵实数部分、虚数部分的指针
mxGetString, 获得字符串内容
mxGetElementSize, 获得存储矩阵元素所需要的字节数
mxCalloc,内存分配。用mxCalloc不用calloc和malloc,因为mxCalloc会自动释放内存,不需要手动free了。
mxCreateString, 创建1*N的字符串矩阵
mxCreateDoubleMatrix, 创建2维双精度浮点矩阵,可以是实数(mxREAL)或者复数(mxCOMPLEX)
mxCreateStructArray, 创建N维结构体矩阵
mxCreateCellMatrix, 创建二维单元矩阵
mxCreateNumericArray,创建n维数值矩阵
mexPrintf, 重新封装的printf
mxSetFiled, 设置结构体矩阵的域
mxSetCell, 设置单元矩阵的单元值
mxSetPr, 设置矩阵实数值
mxSetPi, 设置矩阵虚数值
mxCallMATLAB,调用MATLAB中其他内建函数、自定义M文件、mex文件。
Matlab与C/C++联合编程之Matlab以MEX方式调用C/C++代码(四)的更多相关文章
- Matlab与C/C++联合编程之Matlab以MEX方式调用C代码(五)完整过程加示
如下为本人亲证代码: 一: 编译器的安装与配置(环境不同,显示结果不同) 要使用MATLAB编译器,用户计算机上应用事先安装与MATLAB适配的以下任何一种ANSI C/C++编译器: 5.0.6.0 ...
- Matlab与C/C++联合编程之Matlab以MEX方式调用C/C++代码(一)
MEX文件是一种可在matlab环境中调用的C语言(或fortran)衍生程序,mex的编译结果实际上就是一个带输出函数mexFunction 的dll文件. 中文名 mex文件 外文名 MATLAB ...
- Matlab与C/C++联合编程之Matlab以MEX方式调用C/C++代码(三)
最近写了个Matlab程序,好慢呐……所以开始学习Matlab与C/C++混合编程.下面写了个测试代码,显示一个Double类型矩阵中的元素. 源代码 #include "mex.h&quo ...
- Matlab与C/C++联合编程之Matlab以MEX方式调用C/C++代码(二)
如果我有一个用C语言写的函数,实现了一个功能,如一个简单的函数: double add(double x, double y) { return x + y; } 现在我想要在Matlab中使用它,比 ...
- Matlab以MEX方式调用C源代码【转载】
原文地址:http://blog.sina.com.cn/s/blog_468651400100coas.html 这是自己整理的一个对应的文档:<Matlab以MEX方式调用C源代码> ...
- Matlab以MEX方式调用C源代码
#include "mex.h" // 使用MEX文件必须包含的头文件 // 执行具体工作的C函数 double add(double x, double y) { return ...
- matlab中文论坛视频谷普教程MATLAB压缩包介绍
matlab中文论坛视频谷普教程MATLAB压缩包介绍 我也正在学习这个软件 ,看到这个教程就在这里分享了,希望大家喜欢!Matlab 初学者视频教学1. Matlab视频:Matlab中文论坛为新手 ...
- Matlab中调用第三方Java代码
搞了一天,才算搞定. 第一步:定位Matlab中Java环境的ext目录 新建一个M script文件,或者直接在Matlab的交互式命令行中输入: disp(java.lang.System.get ...
- MATLAB/Excel-如何将Excel数据导入MATLAB中
在使用MATLAB对矩阵进行数据处理时,为了方便编辑与修改,常常需要先将数据录入到Excel中,然后再将其导入到MATLAB中参与矩阵运算.本文在MATLAB 2013a和Office 2013环境下 ...
随机推荐
- Linux定时任务Crontab详解_定时备份
文章来源:http://blog.chinaunix.net/uid-7552018-id-182133.html 今天做了个数据库的备份脚本,顺便系统得学习一下Linux下定时执行脚本的设置.Lin ...
- vim 空格和换行的删除和替换
%s/\s//g %s/\r//g %s/\n//g 把一个很长的一行按空格分为多行 :%s/ +/\r/g简单解释一下:%s :在整个文件范围查找替换/ :分隔符+ :匹配空格,其中“ ”表 ...
- phprpc 使用实例(例实没错却不能执行)函数冲突gzdecode
PHPRPC 是一个轻型的.安全的.跨网际的.跨语言的.跨平台的.跨环境的.跨域的.支持复杂对象传输的.支持引用参数传递的.支持内容输出重定向的.支持分级错误处理的.支持会话的.面向服务的高性能远程过 ...
- samtools常用命令详解(转)
转自:samtools常用命令详解 samtools的说明文档:http://samtools.sourceforge.net/samtools.shtml samtools是一个用于操作sam和ba ...
- webstorm激活码
2016.2.3版本 43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZW ...
- 工作日志 jquery slideDown slideUp
jquery里面使用 slideDown 和 slideUp会有一个像素的偏差
- listbox鼠标拖动数据和为button注册快捷键
将listbox1中的数据用鼠标拖动至listbox2,即有左至右. 分别对应控件注册如下事件DragEnter,MouseDown,DragDrop 代码如下: //P128 DataGridVie ...
- Loadrunner基础:Loadrunner Controller基本概念和使用
Loadrnner Controller 介绍 当Vuser脚本开发完成以后,可以使用Controller将这个执行脚本的用户从单用户转化为多用户,从而模拟大量用户的操作,形成负载(多用户单循环,多用 ...
- JAVA_安装JDK和Eclipse
大二开始前,找的是学长帮忙直接安装的,这个寒假抽空体验重装系统,同时,体验安装JDK和Eclipse.O(∩_∩)O 1.jdk 1)官方网址(下载JDK) http://www.oracle.c ...
- JAVA 数组作业——动手动脑以及课后实验性问题
JAVA课后作业——动手动脑 一:阅读并运行示例PassArray.java,观察并分析程序输出的结果,小结,然后与下页幻灯片所讲的内容进行对照. 1.源代码 // PassArray.java // ...