利用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混合编程所必须的。格式为:

  1. #include “mex.h”
  2. void mexFunction( int nlhs, mxArray *plhs[],
  3. int nrhs, const mxArray *prhs[] )
  4. {
  5. //C语言代码
  6. }

其中入口子程序函数名必须为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,文件内容为:

  1. #include "mex.h"
  2. double add(double x, double y)
  3. {
  4. return x+y;
  5. }
  6. void mexFunction(int nlhs, mxArray *plhs[],int nrhs,const mxArray *prhs[])
  7. {
  8. double a,b,*c;
  9. a=mxGetScalar(prhs[0]);
  10. b=mxGetScalar(prhs[1]);
  11. plhs[0]=mxCreateDoubleMatrix(1,1,mxREAL);
  12. c=mxGetPr(plhs[0]);
  13. *c=add(a,b);
  14. }

首先对文件内容进行简单说明:

其中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文件,内容为:

  1. #include "a.h"
  2. _declspec(dllexportint  add(int a,  int b)  { return a+b; }

为工程添加a.h文件,内容为:

  1. _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++代码(四)的更多相关文章

  1. Matlab与C/C++联合编程之Matlab以MEX方式调用C代码(五)完整过程加示

    如下为本人亲证代码: 一: 编译器的安装与配置(环境不同,显示结果不同) 要使用MATLAB编译器,用户计算机上应用事先安装与MATLAB适配的以下任何一种ANSI C/C++编译器: 5.0.6.0 ...

  2. Matlab与C/C++联合编程之Matlab以MEX方式调用C/C++代码(一)

    MEX文件是一种可在matlab环境中调用的C语言(或fortran)衍生程序,mex的编译结果实际上就是一个带输出函数mexFunction 的dll文件. 中文名 mex文件 外文名 MATLAB ...

  3. Matlab与C/C++联合编程之Matlab以MEX方式调用C/C++代码(三)

    最近写了个Matlab程序,好慢呐……所以开始学习Matlab与C/C++混合编程.下面写了个测试代码,显示一个Double类型矩阵中的元素. 源代码 #include "mex.h&quo ...

  4. Matlab与C/C++联合编程之Matlab以MEX方式调用C/C++代码(二)

    如果我有一个用C语言写的函数,实现了一个功能,如一个简单的函数: double add(double x, double y) { return x + y; } 现在我想要在Matlab中使用它,比 ...

  5. Matlab以MEX方式调用C源代码【转载】

    原文地址:http://blog.sina.com.cn/s/blog_468651400100coas.html 这是自己整理的一个对应的文档:<Matlab以MEX方式调用C源代码> ...

  6. Matlab以MEX方式调用C源代码

    #include "mex.h" // 使用MEX文件必须包含的头文件 // 执行具体工作的C函数 double add(double x, double y) { return ...

  7. matlab中文论坛视频谷普教程MATLAB压缩包介绍

    matlab中文论坛视频谷普教程MATLAB压缩包介绍 我也正在学习这个软件 ,看到这个教程就在这里分享了,希望大家喜欢!Matlab 初学者视频教学1. Matlab视频:Matlab中文论坛为新手 ...

  8. Matlab中调用第三方Java代码

    搞了一天,才算搞定. 第一步:定位Matlab中Java环境的ext目录 新建一个M script文件,或者直接在Matlab的交互式命令行中输入: disp(java.lang.System.get ...

  9. MATLAB/Excel-如何将Excel数据导入MATLAB中

    在使用MATLAB对矩阵进行数据处理时,为了方便编辑与修改,常常需要先将数据录入到Excel中,然后再将其导入到MATLAB中参与矩阵运算.本文在MATLAB 2013a和Office 2013环境下 ...

随机推荐

  1. Java 数据类型之间的转换 拆分字符串 Date/Calendar的转换

    数据类型转换 1. String - Int String str="123"; int i=1; int str=Integer.parseInt(str); String i= ...

  2. entity refenrece 在views中的运用

    在一个content type中有一个field是entity reference, 那么这个字段的设置过程中会指定一个entity type和content type和一个具体内容的选择器, 然后到 ...

  3. centos下vsftpd安装与配置

    1.已经配置好可以上网了,所以即可通过yum install vsftpd安装啦.如果不能上网则可以通过dvd2.iso工具集rpm方式进行安装. 2.安装好后,默认本地可以通过匿名用户登录,但是其它 ...

  4. android AutoCompleteTextView 自定义BaseAdapter

    最近项目中需要做搜索功能,实现类似 Google.Baidu 搜索的 下拉提示效果.Android为我们提供了 AutoCompleteTextView 控件来完成此功能. 网上好多例子都是简单使用 ...

  5. C# EXCEL(.xls和.xlsx)导入到数据库

    C# EXCEL(.xls和.xlsx)导入到数据库  转(http://www.cnblogs.com/bart-cai/articles/2716555.html) 原理:1.判断是否是Excel ...

  6. 例子:使用C++中的this

    在C++中很多的东西都传值的,. C++中的对象之间的copy是传值的 , 他不想java那样,对象之间传递的引用 , 或者说是java对指针进行了封装 , 禁止了一些不安全的操作 对于C++而言 , ...

  7. hdu 1805Expressions(二叉树构造的后缀表达式)

    Expressions Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  8. HDUOJ--------A simple stone game(尼姆博弈扩展)(2008北京现场赛A题)

    A simple stone game                                                                                  ...

  9. hdu-----2491Priest John's Busiest Day(2008 北京现场赛G)

    Priest John's Busiest Day Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav ...

  10. Gas Station [LeetCode]

    There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. You ...