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. strstr-strcat实现

    strstr 调用格式 #include <string.h> char *strstr(const char *haystack, const char *needle); 功能说明 该 ...

  2. android 自己定义水平和圆形progressbar 仅仅定义一些style就能够

    效果图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/diss ...

  3. 【机器学习具体解释】SVM解二分类,多分类,及后验概率输出

    转载请注明出处:http://blog.csdn.net/luoshixian099/article/details/51073885 CSDN−勿在浮沙筑高台 支持向量机(Support Vecto ...

  4. 【Java 虚拟机探索之路系列】:JIT编译器

    作者:郭嘉 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells github:https://github.com/AllenWell 为 ...

  5. Linux-github 搭建静态博客

    1.在Github上创建一个新的Repository 到你的github上 https://github.com去create a new repository命名为 github.myblog 2. ...

  6. 【OpenCV新手教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/26977557 作者:毛星云(浅墨) ...

  7. 3.2.1 配置构建Angular应用——简单的笔记存储应用——编辑功能

    本节我们会接着上节课的内容,继续来完成使用Angular来创建简单的笔记存储应用,上一节课,我们完成了笔记的展示功能,本节课,我们来完成编辑功能. 编辑主要是两个功能:编辑现有的笔记以及创建新笔记.首 ...

  8. android 怎样将主菜单图标改成按安装时间排序

    1. 在 LauncherModel.java 中增加例如以下代码, 假设是KK Launcher3 ApplicationInfo要替换为AppInfo public static final Co ...

  9. instruction set汇总

    1 aarch64 它armv8-A架构的一种执行状态,之所以说它是一种执行状态是因为,armv8-A还有aarch32这个执行状态.aarch64是64位执行状态,aarch32是32位的执行状态. ...

  10. 包管理 import debug 模块管理 module

    import sys, os this_file_abspath = os.path.dirname(os.path.abspath(__file__)) ProjectUtil_path = '{} ...