Matlab调用C程序 分类: Matlab c/c++ 2015-01-06 19:18 464人阅读 评论(0) 收藏
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) 收藏的更多相关文章
- Raspberry Pi + 3个USB摄像头 + Motion(简易监控设备配置记录1——介绍以及安装) 分类: Raspberry Pi 服务器搭建 2015-04-12 19:21 226人阅读 评论(0) 收藏
参考: Debian官网链接 Motion官网链接 首先,参见Debian官网链接对Motion的介绍,网页中包含了所有相关依赖包,请首先确保这些依赖包的安装. Motion介绍 摘出对Motion的 ...
- linux常用的压缩与解压缩命令 分类: 学习笔记 linux ubuntu 2015-07-05 19:38 38人阅读 评论(0) 收藏
1.gzip 压缩 gzip 是压缩文件,压缩之后文件后缀为.gz 用法:gzip 选项 [文件] 2.gunzip 解压 这个命令与gzip的功能刚好相反,这个是解压. 用法 gunzip 选项 [ ...
- linux中的帮助命令 分类: linux 学习笔记 ubuntu 2015-07-05 19:07 31人阅读 评论(0) 收藏
说实话,到目前为止我还是不太习惯使用linux自带的帮助文档,遇到问题都是去查我自己下载的chm格式的命令大全,不过这些帮助命令我们还是有必要了解的. 1.man [要查看的命令名称] 例如想要查看l ...
- APP被苹果APPStore拒绝的各种原因 分类: ios相关 app相关 2015-06-25 17:27 200人阅读 评论(0) 收藏
APP被苹果APPStore拒绝的各种原因 1.程序有重大bug,程序不能启动,或者中途退出. 2.绕过苹果的付费渠道,我们之前游戏里的用兑换码兑换金币. 3.游戏里有实物奖励的话,一定要说清楚,奖励 ...
- 全面解析sizeof(上) 分类: C/C++ StudyNotes 2015-06-15 10:18 188人阅读 评论(0) 收藏
以下代码使用平台是Windows7 64bits+VS2012. sizeof是C/C++中的一个操作符(operator),其作用就是返回一个对象或者类型所占的内存字节数,使用频繁,有必须对齐有个全 ...
- 不定义JQuery插件,不要说会JQuery 分类: JavaScript 2014-11-24 14:18 155人阅读 评论(0) 收藏
一:导言 有些WEB开发者,会引用一个JQuery类库,然后在网页上写一写$("#"),$("."),写了几年就对别人说非常熟悉JQuery.我曾经也是这样的人 ...
- 苹果应用商店AppStore审核中文指南 分类: ios相关 app相关 2015-07-27 15:33 84人阅读 评论(0) 收藏
目录 1. 条款与条件 2. 功能 3. 元数据.评级与排名 4. 位置 5. 推送通知 6. 游戏中心 7. 广告 8. 商标与商业外观 9. 媒体内容 10. 用户界面 11. 购买与货币 12. ...
- Run Loop简介 分类: ios技术 ios相关 2015-03-11 22:21 73人阅读 评论(0) 收藏
做了一年多的IOS开发,对IOS和Objective-C深层次的了解还十分有限,大多还停留在会用API的级别,这是件挺可悲的事情.想学好一门语言还是需要深层次的了解它,这样才能在使用的时候得心应手,出 ...
- iOS Socket第三方开源类库 ----AsyncSocket 分类: ios相关 ios技术 2015-03-11 22:14 59人阅读 评论(0) 收藏
假如你也是一个java程序员,而你又不是很懂Socket. 下面我的这篇文章也许能帮助你一些. http://xiva.iteye.com/blog/993336 首先我们写好上面文章中的server ...
随机推荐
- Python - 多次检查后缀名(endwith)
在通过后缀名查找类型文件的时候, 多次使用endwith, 使用元组(tuple), 简化操作. 此类方式, 也能够应用于if语句多次类似检測. 代码 # 列出目录内全部代码 def list_dic ...
- angular $resource 的 get请求 和 post请求
1.语法: $resource(url,[paramDefaults],[actions],options); 详解: (1)url:一个参数化的url模板 (2)paramDefaults:url参 ...
- GLib-GObject-WARNING **: Two different plugins tried to register
使用 Ubuntu vivid 的 glib-2.44.1 的程序总是打印类似这种警告: GLib-GObject-WARNING **: Two different plugins tried to ...
- 通过GhostDoc实现自定义方法概要(summary)
首先是下载GhostDoc 来自园友:http://www.cnblogs.com/VAllen/p/GhostDocPro49.html 修改模板 安装好后,修改下模板,工具>GhostDoc ...
- 2016/3/26 weixin 头像 昵称 网页优化显示 缺表中数据 只有代码 无显示效果
weixin.php <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
- mysql 5.5安装不对容易出现问题
按照正常步骤安装完了mysql 5.5之后,再运行一下bin目录中的mysqlinstanceconfig.exe,重置一下密码!!!! 重置密码的地方:modify security setting ...
- mysql14---手动备份
PHP定时完成数据库的备份 1.手动备份数据库(表的)方法 cmd控制台(windows指令): mysqldump –u root –proot 数据库 [表名1 表名2..] > 文件路径 ...
- oracle经典建表语句--scott建表
create table EMP ( EMPNO ) PRIMARY KEY, ENAME ), JOB ), MGR ), HIREDATE DATE, SAL ,), COMM ,), DEPNO ...
- assert的作用是什么
assert()宏是用于保证满足某个特定条件,用法是: assert(表达式); 如果表达式的值为假,整个程序将退出,并输出一条错误信息.如果表达式的值为真则继续执行后面的语句. 使用这个宏前需要包含 ...
- YTU 2580: 改错题----修改revert函数
2580: 改错题----修改revert函数 时间限制: 1 Sec 内存限制: 128 MB 提交: 194 解决: 82 题目描述 修改revert函数,实现输入N个数,顺序倒置后输出 #i ...