Matlab是矩阵语言,如果运算可以用矩阵实现,其运算速度非常快。但若运算中涉及到大量循环,Matlab的速度令人难以忍受的。当必须使用for循环且找不到对应的矩阵运算来等效时,可以将耗时长的函数用C语言实现,并编译成Mex文件,Matlab便可以像调用内建函数一样调用C编写的函数。Mex文件其实是一种动态链接库,旧版本Matlab可以直接调用.dll,新版本要调用.mexw32或.mexw64文件。

编译过程需要C语言编译器,在Matlab中键入mex –setup进行安装与配置。

MEX文件的源代码组成

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

(2)入口子程序。该过程提供功能子程序与Matlab之间的接口,以mexFunction函数实现。注意,入口过程的名称必须是mexFunction,并且包含四个参数,即

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

nrhs(left hand side): 输入参数的个数;

prhs是一个输入数组,其内容为指针,指向mxArray类型的数据(MATLAB中所有数据都是以矩阵的形式mxArray保存的)。

nlhs, plhs含义类似。

具体地,若在Matlab中执行[a,b]=test(c,d,e) ,则nlhs=2, nrhs=3,prhs[0]指向c,prhs[1]指向d,prhs[2]指向e(可以理解为:prhs[0]=&c, prhs[1]=&d, prhs[2]=&e),注意prhs是const指针数组,故不能改变其指向内容;函数返回时将plhs[0],plhs[1]指向的内容赋给a,b(可以理解为a=*plhs[0], b=*plhs[1])。

:新建add.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;
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);
}

将add.c拷贝至Matlab当前目录,执行mex add.c,生成add.mexw64,该文件实现求和功能。此时便可在Matlab中调用该函数:

>> output = add(1.1, 2.2);

分析:

#include "mex.h"

Mex源文件必须包含mex.h,该头文件提供了大量Matlab与C(或Fortran)语言的之间的接口函数,函数前缀有mex-和mx-两种,带mx-前缀的大多是对mxArray数据进行操作的函数,如mxIsDouble,mxCreateDoubleMatrix等;而带mex-前缀的则大多是与Matlab环境进行交互的函数,如mexPrintf,mexErrMsgTxt等。具体可参考Apiref.pdf

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

建立一个1x1的double类型的矩阵,返回刚建立的mxArray的地址,赋给指针plhs[0];

a = mxGetPr(plhs[0]);

返回指针plhs[0]所指向矩阵的第一个实数的地址,并赋给a;

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

获取指针prhs[0]指向矩阵的第一个实数,并赋给b;

*a = add(b, c);

调用C程序add,计算b,c之和并赋给a指向的内容;

例:新建myhilb.c,源码如下:

#include "mex.h"
void myhilb(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;
if (nrhs!=1)
mexErrMsgTxt("One inputs 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);
y=mxGetPr(plhs[0]);
myhilb(y,(int)x);
}

将myhilb.c拷贝至Matlab当前目录,执行mex myhilb.c,生成myhilb.mexw64,该文件实现了计算Hilbert矩阵的功能(Hilbert矩阵:H(i,j)=1/(i+j-1))。

此时便可在Matlab中调用该函数:

>> output = myhilb (6);

分析:

mexFunction中进行了参数检查,函数mexErrMsgTxt显示出错信息后即退回到MATLAB。

mxGetScalar:获取输入矩阵第一个元素的实数部分;mxGetM:获取矩阵的行数。

为了测试一下Mex文件与m文件的速度差异,编写m文件并运行之:

tic
m=10000;
a=zeros(m,m);
for i=1:m
for j=1:m
a(i,j)=1/(i+j);
end
end
toc

结果:Elapsed time is3.620924 seconds.

接着运行Mex文件

tic
output = myhl(10000);
toc

结果:Elapsed timeis 0.730596 seconds.

可以看出Mex文件与M文件速度差异很大。

VS2010生成Mex文件(本人64位操作系统)

上述利用Matlab编译生成Mex文件,同样也可以使用VS2010生成Mex文件,只不过需要对VS环境进行配置,过程如下:

1、  新建一个win32 控制台的dll 空项目”myhilb”;

2、  新建源文件myhilb.c,将上述myhilb.c内容拷进即可;

3、  添加.def文件,内容为:

LIBRARY

EXPORTSmexFunction

4、  配置项目属性, 打开项目属性配置页:

(1)C/C++—>常规—>附加包含目录,输入matlab下安装目录下\extern\include

本人输入E:\Matlab2010\Install\extern\include

(2)链接器->常规—>附加库目录,输入matlab下安装目录下\extern\lib\win64\microsoft

本人输入E:\Matlab2010\Install\extern\lib\win64\microsoft

(3)连接器 ->输入->附加依赖项,输入

libmx.lib

libeng.lib

libmat.lib

libmex.lib

(4)链接器->常规—>输出文件,输入$(OutDir)$(TargetName).mexw64(若此处不更改,可在生成dll文件后将后缀名改为mexw64即可,这也验证了Mex实际上就是DLL,只是后缀名不同罢了)

(5)链接器->高级—>目标计算机,设为MachineX64(32位系统不用更改)

设置好点击应用,执行了(5)的64位系统还需要在执行:

生成—>配置管理器—>活动解决平台,改为x64

5、按F7编译工程,会在Debug下生成.mexw64文件,如下图:

VS中单步调试Mex文件

在Matlab环境下使用 mex  –g myhilb.c命令进行调试,但无法加断点进行单步调试,故需转到VS环境下调试。

不管是利用VS还是利用Matlab生成Mex文件,只要有c源文件和Mex文件就可以利用VS对Mex源程序加断点进行单步调试(我们用上面myhilb.c和myhilb.mexw64做测试)。

1、将Matlab当前目录改为Mex文件(C文件)所在目录;

2、在VS2010中打开C文件,调试—>附加到进程,附加MATLAB.exe;

3、VS中在C源码中添加断点,在Matlab命令窗口调用Mex文件提供的接口;

如Matlab执行:out=myhilb(6);

此时,VS2010中便可按F10进行单步调试:

要说明的是,在调试阶段Matlab处于假死状态,另外,Matlab调用了Mex文件后需要执行clear all命令后才能删除Mex文件;

同样地,若利用VS生成Mex文件后直接将Matlab当前目录改至Debug目录进行调试,则调试完必须执行clear all指令才能重新编译工程。

参考:

http://blog.sina.com.cn/s/blog_468651400100coas.html

http://www.cppblog.com/xiaozhixd/articles/108490.html

http://www.linuxidc.com/Linux/2012-08/68148.htm

http://blog.sina.com.cn/s/blog_a7e72e940101cti9.html

http://blog.csdn.net/raodotcong/article/details/6317273

版权声明:本文为博主原创文章,未经博主允许不得转载。

Matlab调用C程序 分类: Matlab c/c++ 2015-01-06 19:18 464人阅读 评论(0) 收藏的更多相关文章

  1. Raspberry Pi + 3个USB摄像头 + Motion(简易监控设备配置记录1——介绍以及安装) 分类: Raspberry Pi 服务器搭建 2015-04-12 19:21 226人阅读 评论(0) 收藏

    参考: Debian官网链接 Motion官网链接 首先,参见Debian官网链接对Motion的介绍,网页中包含了所有相关依赖包,请首先确保这些依赖包的安装. Motion介绍 摘出对Motion的 ...

  2. linux常用的压缩与解压缩命令 分类: 学习笔记 linux ubuntu 2015-07-05 19:38 38人阅读 评论(0) 收藏

    1.gzip 压缩 gzip 是压缩文件,压缩之后文件后缀为.gz 用法:gzip 选项 [文件] 2.gunzip 解压 这个命令与gzip的功能刚好相反,这个是解压. 用法 gunzip 选项 [ ...

  3. linux中的帮助命令 分类: linux 学习笔记 ubuntu 2015-07-05 19:07 31人阅读 评论(0) 收藏

    说实话,到目前为止我还是不太习惯使用linux自带的帮助文档,遇到问题都是去查我自己下载的chm格式的命令大全,不过这些帮助命令我们还是有必要了解的. 1.man [要查看的命令名称] 例如想要查看l ...

  4. APP被苹果APPStore拒绝的各种原因 分类: ios相关 app相关 2015-06-25 17:27 200人阅读 评论(0) 收藏

    APP被苹果APPStore拒绝的各种原因 1.程序有重大bug,程序不能启动,或者中途退出. 2.绕过苹果的付费渠道,我们之前游戏里的用兑换码兑换金币. 3.游戏里有实物奖励的话,一定要说清楚,奖励 ...

  5. 全面解析sizeof(上) 分类: C/C++ StudyNotes 2015-06-15 10:18 188人阅读 评论(0) 收藏

    以下代码使用平台是Windows7 64bits+VS2012. sizeof是C/C++中的一个操作符(operator),其作用就是返回一个对象或者类型所占的内存字节数,使用频繁,有必须对齐有个全 ...

  6. 不定义JQuery插件,不要说会JQuery 分类: JavaScript 2014-11-24 14:18 155人阅读 评论(0) 收藏

    一:导言 有些WEB开发者,会引用一个JQuery类库,然后在网页上写一写$("#"),$("."),写了几年就对别人说非常熟悉JQuery.我曾经也是这样的人 ...

  7. 苹果应用商店AppStore审核中文指南 分类: ios相关 app相关 2015-07-27 15:33 84人阅读 评论(0) 收藏

    目录 1. 条款与条件 2. 功能 3. 元数据.评级与排名 4. 位置 5. 推送通知 6. 游戏中心 7. 广告 8. 商标与商业外观 9. 媒体内容 10. 用户界面 11. 购买与货币 12. ...

  8. Run Loop简介 分类: ios技术 ios相关 2015-03-11 22:21 73人阅读 评论(0) 收藏

    做了一年多的IOS开发,对IOS和Objective-C深层次的了解还十分有限,大多还停留在会用API的级别,这是件挺可悲的事情.想学好一门语言还是需要深层次的了解它,这样才能在使用的时候得心应手,出 ...

  9. iOS Socket第三方开源类库 ----AsyncSocket 分类: ios相关 ios技术 2015-03-11 22:14 59人阅读 评论(0) 收藏

    假如你也是一个java程序员,而你又不是很懂Socket. 下面我的这篇文章也许能帮助你一些. http://xiva.iteye.com/blog/993336 首先我们写好上面文章中的server ...

随机推荐

  1. 问题解决:FFmpeg视频编解码库,无法解析的外部信号

    在编译FFmpeg相关项目时.可能会出现: error LNK2019: 无法解析的外部符号 "int __cdecl avpicture_fill(struct AVPicture *,u ...

  2. 避免使用vector&lt;bool&gt;

     作为一个STL容器,vector<bool>仅仅有两点不正确. 首先.它不是一个STL容器. 其次,它并不存储bool.除此之外.一切正常. 一个对象要成为容器,就必须满足C++标准 ...

  3. org.json.JSONException: A JSONObject text must begin with &#39;{&#39; at character 1 of {解决方法

    在使用java读取一个本地的json配置文件的时候,产生了这个异常:org.json.JSONException: A JSONObject text must begin with '{' at c ...

  4. PHP swfupload图片上传实例

    swfupload已经是第二次研究,这次自已整了个简单demo,无奈菜鸟最杯… PHP代码如下: if (isset($_FILES["Filedata"]) || !is_upl ...

  5. 使用JS对select标签进行联动选择

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  6. onDestroy强制退出后,process crash的处理

    from http://bbs.9ria.com/thread-248722-1-1.html     一般情况,我们在执行测试的过程中都会调用tearDwon方法,以Robotium为例,我们在te ...

  7. Unable to find a team with the given Team ID或者Failed to code sign的问题解决

    Unable to find a team with the given Team ID或者Failed to code sign的问题解决 1:问题描述(注:这种情况一般是下载并打开别人项目时) F ...

  8. 2014/4/18 ① button与submit的区别 ②现象 : 数据库中其他值可以取到 有的却取不到 解决 看获取时“#”有无

    ①<input type="button" /> 这就是一个按钮.如果你不写javascript 的话,按下去什么也不会 发生. <input type=&quo ...

  9. 2015/12/25 ① 图灵测试 ② 安装jdk出现的问题 ③ 配置环境变量

    ①图灵测试 1,解释 图灵测试一词来源于计算机科学和密码学的先驱阿兰·麦席森·图灵写于1950年的一篇论文<计算机器与智能>.阿兰·麦席森·图灵1950年设计出这个测试,其内容是,如果电脑 ...

  10. mysql08---优化01

    Mysql数据库的优化技术 对mysql优化时一个综合性的技术,主要包括 a: 表的设计合理化(符合3NF) b: 添加适当索引(index) [四种: 普通索引(什么都不写).主键索引(有一个主键 ...