Matlab与C/C++混合编程有很多种方式,分别适用于不同的情况。

  1. 程序主体用Matlab编写,有一些特别耗时的函数用C/C++改写来提高效率,或者已经有现成的C/C++函数,应用到Matlab程序中(本文属于这种情况)
  2. 程序主体用C/C++编写,部分程序想调用Matlab函数减少开发时间,本文不涉及这种情况,建议读者自行查阅Matlab帮助文档

一点点废话

Matlab有着非常详细的帮助文档,建议直接阅读其帮助文档,市面上很多Matlab书籍都是简单的翻译翻译帮助文档,例子都是照抄,还有很多错误和断章取义的地方,参考这样的书籍容易被带上弯路。

打开Matlab,按F1打开帮助,此部分内容在:

MATLAB->Advanced Software Development->MATALB API for Other Languages

什么是MEX-file

简单来说MEX-file是一种预编译的,用其他语言(C/C++,Fortran)编写的函数库,可以直接被Matlab调用。

正如前面提到的,这种方式适用于两种情况:

  1. 程序中有一部分代码耗时巨大,想通过改写这部分函数提高速度
  2. 已经有大量C/C++或Fortran的函数库,想直接用Matlab调用,避免重复开发

这两种情况用MEX-file的这种方案来解决都是非常合适的,因为这种调用方式非常方便,你需要注意地只是数据结构的转换。这种方式支持C/C++和Fortran,本文主要将C/C++。

如何创建可供Matlab直接调用的MEX-file

1.安装Matlab支持的编译器

在Matlab命令窗口输入:

mex -setup

如果你的电脑已经安装了Matlab支持的编译器,这时候你应该会看到设置编译器的提示命令,跟着一步步下去就可以了。

注意:如果你电脑只安装了一个支持的编译器,这一步会自动用此编译器进行配置,如果有多个支持的编译器,Matlab会引导你选择要使用哪个编译器。 如果你电脑没有安装合适的编译器,会得到一个错误,提示你安装合适的编译器,并给出一个支持编译器列表的链接。

2.创建.c/.cpp文件

这一步可以用Matlab的编辑器也可以用其他你喜欢的编辑器,需要注意的是: 将来在Matlab中调用的函数名即为此处你创建的文件名,而不是文件内的函数名

MEX-file的内容

一个完整的MEX-file应该包括:

  • #include <mex.h> MEX-file头文件
  • mexFunction 入口函数(C/C++中的main函数)
  • 输入输出的数据的校验
  • 变量的传递
  • 你自己编写的功能函数

mexFunction 入口函数

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

此函数是MEX-file的入口函数,形式比较固定,起着C/C++语言中main函数的作用,建议放在整个文件的最后。

mexFunction函数中一般只做数据的转换和其他函数的调用,不做复杂的处理。

  • prhs -函数右侧,输入参数
  • plhs -函数左侧,输出参数
  • nrhs -函数右侧,输入参数的个数
  • nlhs -函数左侧,输出参数的个数

例如:在Matlab中用[a,b]=myMEX(c,d,e)的形式调用的函数,则nrhs==3 代表有三个输入参数,nlhs==2代表有两个输入参数,参数值分别储存在prhsplhs中。 输入输出数据的校验

这一部分建议放在mexFunction里面,校验输入输出参数的个数是否符合要求,校验输入参数的类型是否符合要求。

这里的输入参数是 只读 的,不要尝试更改,不然会引起错误。

创建一个可更改的输入参数的副本myData并调用mxDuplicateArray函数:

mxArray *myData = mxCreateStructMatrix(1,1,nfields,fnames); mxSetField(myData,0,"myFieldName",mxDuplicateArray(prhs[0])); 

对于输入参数类型的校验可以用mxIsClass中的函数来进行:

if(mxIsSparse(prhs[1])||mxIsComplex(prhs[1])||mxIsClass(prhs[1],"char")) { mexErrMsgTxt("input2 must be full matrix of real values."); } 

完整的mxIsClass函数列表见附录。

3.变量的传递

这一部分主要涉及如何将输入参数中的数据传出,并且用C/C++的数据结构来表示,以及如何构建输出参数,将运算结果传回Matlab。

由于Matlab中数据结构种类比较多,且比较复杂,这里并不会一一涉及,只介绍几种比较常用的数据类型,其他数据类型大家可以自行查阅Matlab帮助文档。

以下的示例代码都假设你需要传递的输入参数是第一个,如果为其他,只需修改prhs的角标即可

标量的传递

size_t mrows;  //行数
size_t ncols; //列数 double scalar; //接收输入参数的变量 mrows = mxGetM(prhs[0]); //获取矩阵行数 ncols = mxGetN(prhs[0]); //获取矩阵列数 /*校验输入是否是一个标量*/ if( !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || !(mrows==1 && ncols==1) ) { mexErrMsgIdAndTxt( "MATLAB:timestwo:inputNotRealScalarDouble","Input must be a noncomplex scalar double."); } scalar = mxGetScalar(prhs[0]); //获取标量值 

矩阵的传递

size_t mrows;    //行数
size_t ncols; //列数 mxArray *inMat; //接收输入参数的指针 mrows = mxGetM(prhs[0]); //获取矩阵行数 ncols = mxGetN(prhs[0]); //获取矩阵列数 /*校验输入是否是一个3*4的double矩阵 矩阵维数的校验也可以去掉(相应的你的处理函数要有处理不同大小矩阵的能力)*/ if( !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || !(mrows==3 && ncols==4) ) { mexErrMsgIdAndTxt( "MATLAB:timestwo:inputNotRealScalarDouble", "Input must be a noncomplex double matrix."); } /*获取输入矩阵的指针*/ inMat = mxGetPr(prhs[0]); 

为输出变量分配内存并传递给mexFunction的输出参数

mxArray *outMat;
outMat = mxCreateDoubleMatrix((mwSize)mrows,(mwSize)ncols,mxREAL); plhs[0] = outMat; 

这里需要注意的是Matlab中矩阵的储存是列优先的,而C语言中是行优先的,在调用矩阵元素时需要注意:

double result;/* 将iMat中的第 i行 j列的元素值赋给result */
result = inMat[j*mrows+i] 

为输出变量分配内存并传递给mexFunction的输出参数

mxArray *outMat;
outMat = mxCreateDoubleMatrix((mwSize)mrows,(mwSize)ncols,mxREAL); plhs[0] = outMat; 

字符串的传递

将输入参数转换为C-typestring

string input_buf;
input_buf = mxArrayToString(prhs[0]); 

为输出字符串分配内存

string output_buf;
output_buf=mxCalloc(buflen, sizeof(char)); 

将输出字符串传递给输出参数

plhs[0] = mxCreateString(output_buf); 

最后释放内存

mxFree(input_buf);

Structure和Cell类型的传递

StructureCell类型的传递其实与其他类型相似,他们是mxArray类型。

mxGetFieldmxGetCell函数可以用来获取指向StructureCell类型内容的mxArray类型的指针。

mxGetNumberOfFieldsmxGetNumberOfElements可以用来获取Structure的条目的个数和元素的个数。

mxGetData函数可以用来获取mxArray变量中包含的数据。

因为Matlab中Cell的应用比Structure频繁,并且这两者结构数据传递方式很类似,此处以Cell进行讲解: 假设我们的输入参数Cell中第一个元素是一个1x3的矩阵,第二个元素还是一个Cell,这个Cell里面包含两个1x3的矩阵,在Matlab中构建方法如下:

temp    = [];
temp{1} = [1:3]; temp{2} = [4:6]; Cell = []; Cell{1} = [1:3]; Cell{2} = temp; 

现在我们如果我们想将Cell传入MEX-file中进行处理,读出Cell中第第一个元素[1:3]和第二个元素temp,这个元素还是一个Cell,这在Matlab中很常见,可以如下操作:

mxArray *mat;   //指向第一个元素[1:3]的指针 mxArray *Cell; //指向第二个元素的指针,还是一个Cell size_t nrows; //行数 size_t ncols; //列数 double *data; //数据 int i; //循环变量 int j; /* 获取输入Cell的维数 */ mrows = mxGetM(prhs[0]); ncols = mxGetN(prhs[0]); /* 输出Cell的维数,这里作为示例我并没有保存Cell的维数,后面获取Cell中元素维数时还是用的这两个变量 */ mxPrintf("rows:%d,cols:%d\n",mrows,ncols); /* 取出Cell中第一个元素,此处mat是一个指向矩阵的mxArray指针,data储存的是数据 */ mat = mxGetCell(prhs[0],0); data = (double*)mxGetData(mat); /* 打印矩阵内的元素 [1:3]*/ mrows = mxGetM(mat); ncols = mxGetN(mat); for (i=0;i<mrows;i++) { for (j=0;j<ncols;j++) { mxPrintf("%f ",data[j*M+i]); } mxPrintf("\n"); } /* 取出Cell中第二个元素 还是一个Cell 再取出里面内容的方法与上述过程一致 继续调用mxGetCell */ Cell = mxGetCell(prhs[0],1); 

关于在Mex-file中构建Cell的方法,这里不详细讲了,因为个人觉得这么做吃力不讨好,何不把数据分别传入Matlab再重新组织呢?如果你真的想要在MEX-file里面构建Cell并传出,原理是创建一个相应大小的mxArray,因为Cell本身就是mxArrary类型的,然后将这部分内存的地址传给plhs

MEX-file的编译和调用

将Matlab的当前目录切换到你MEX-file所在的目录,假设你的文件名为helloMEX.c,在Matlab命令窗口输入

mex helloMEX.c

如果得到MEX completed successfully.的提示即为编译成功,如果不成功,会显示错误的位置和原因,对应修改即可。

编译成功后会得到后缀为.mexw64的文件(后缀名与平台相关,此为win64下的后缀名,其他平台不同),将此文件添加入Matlab的路径中,或者将当前目录切换到此文件所在目录,即可像普通的Matlab函数一样调用此文件。

附录: mxIsClass 函数列表

(更详细的介绍参见Matlab帮助文档)

mxIsDouble() //Determine whether mxArray represents data as double-precision, floating-point numbers
mxIsSingle() //Determine whether array represents data as single-precision, floating-point numbers mxIsComplex() //Determine whether data is complex mxIsNumeric() //Determine whether array is numeric mxIsInt64() //Determine whether array represents data as signed 64-bit integers mxIsUint64() //Determine whether array represents data as unsigned 64-bit integers mxIsInt32() //Determine whether array represents data as signed 32-bit integers mxIsUint32() //Determine whether array represents data as unsigned 32-bit integers mxIsInt16() //Determine whether array represents data as signed 16-bit integers mxIsUint16() //Determine whether array represents data as unsigned 16-bit integers mxIsInt8() //Determine whether array represents data as signed 8-bit integers mxIsUint8() //Determine whether array represents data as unsigned 8-bit integers mxIsChar() //Determine whether input is string array mxIsLogical() //Determine whether array is of type mxLogical mxIsLogicalScalar() //Determine whether scalar array is of type mxLogical mxIsLogicalScalarTrue() //Determine whether scalar array of type mxLogical is true mxIsStruct() //Determine whether input is structure array mxIsCell() //Determine whether input is Cell array mxIsClass() //Determine whether array is member of specified class mxIsInf() //Determine whether input is infinite mxIsFinite() //Determine whether input is finite mxIsNaN() //Determine whether input is NaN (Not-a-Number) mxIsEmpty() //Determine whether array is empty mxIsSparse() //Determine whether input is sparse array mxIsFromGlobalWS() //Determine whether array was copied from MATLAB global workspace mxAssert() //Check assertion value for debugging purposes mxAssertS() //Check assertion value without printing assertion text

转载于:https://www.cnblogs.com/ynnie/p/9239347.html

Matlab与C/C++混合编程 Matlab调用C函数相关推荐

  1. 【转】matlab与C/C++混合编程——在Windows/Linux上调用Matlab编译的动态库文件

    转自:matlab与C/C++混合编程--在Windows/Linux上调用Matlab编译的动态库文件_sinat_18131557的博客-CSDN博客 date version comments ...

  2. Matlab与C/C++混合编程调用OpenCV

    *************************************************** 更多精彩,欢迎进入:http://shop115376623.taobao.com http:/ ...

  3. matlab和C/C++混合编程--Mex

    最近的项目需要matlab和C的混合编程,经过一番努力终于完成了项目要解决的问题.现在就将Mex的一些经验总结一下,当然只是刚刚开始,以后随着学习的深入继续添加.首先讲讲写Mex的一些常规规定,然后我 ...

  4. Matlab与C/C++混合编程接口及应用

    http://www.cnblogs.com/lidabo/archive/2012/08/24/2654148.html 在参考文献基础上.补充和完善了. Matlab与C/C++混合编程接口及应用 ...

  5. Matlab与C/C++混合编程 (基于Opencv库)

    之前用过基于VS2018 与MATLAB2018a 混合编程(C++特性)(见https://blog.csdn.net/wwwoowww/article/details/83013801),奈何后来 ...

  6. matlab与c 接口与混合编程,Matlab与C/C++混合编程接口及应用方法解析

    1 引言 Matlab 是当前应用最为广泛的数学软件,具有强大的数值计算.数据分析处理.系统 分析.图形显示甚至符号运算等功能[1].利用这一完整的数学平台,用户可以快速实现十分 复杂的功能,极大地提 ...

  7. matlab和C/C++混合编程--Mex (转载)

    matlab和C/C++混合编程--Mex 最近的项目需要matlab和C的混合编程,经过一番努力终于完成了项目要解决的问题.现在就将Mex的一些经验总结一下,当然只是刚刚开始,以后随着学习的深入继续 ...

  8. matlab与vs混合编程,matlab与vs混合编程/matlab移植

    前言 项目算法中包含了不同编译工具的代码,分别是matlab和VS,需要将二者结合起来,统一在同一个系统工作,此时就要用到matlab和vs混合编程. 在matlab中将.m文件编译生成库文件等供外部 ...

  9. MATLAB和C语言混合编程示例

    MATLAB虽然很好用,尤其在数值运算,图像处理,仿真方面很简洁.方便,但有时间当处理比较大的数据时速度确实有点让人捉急,不过MATLAB提供了和C/C++混合编程的接口,以此兼具二者的优点来缓解这个 ...

  10. matlab和C/C++混合编程--Mex (六)参数传递

    最近的项目需要matlab和C的混合编程,经过一番努力终于完成了项目要解决的问题.现在就将Mex的一些经验总结一下,当然只是刚刚开始,以后随着学习的深入继续添加.首先讲讲写Mex的一些常规规定,然后我 ...

最新文章

  1. 『TensorFlow』数据读取类_data.Dataset
  2. @芥末的糖----------《管理系统后台架构逻辑》
  3. 纯数学教程 Page 203 例XLI (1)
  4. 【迁移学习(Transfer L)全面指南】方差、协方差和Pearson相关系数的关系
  5. android 获取其他布局,android listview onItemClick中获取其他item的布局
  6. Linux根据端口号查进程
  7. eltree ref什么时候有_成功el-tree从接口取数据
  8. linux vim(gvim) 多标签页,Vim 的标签页功能
  9. Android4.4 ContentResolver查询图片无效 及 图库删除 添加图片后,ContentResolver不更新的问题解决...
  10. Java中九大内置对象
  11. android 筛选菜单_使用C语言开发跨平台(win/android)应用(PainterEngine 快速入门教程)...
  12. SAP License:供应链管理和ERP的关系?
  13. 文本词频统计是字典吗_TF-IDF词频逆文档频次算法
  14. MFC 消息映射表和虚函数实现消息映射到底谁的效率高
  15. 查看谁连接oracle,oracle如何查看当前有哪些用户连接到数据库
  16. 计算机平面设计培训学费,个旧计算机平面设计学校学费多少
  17. 嵌入式、单片机之间的区别
  18. 科技大停滞--过去已逝,未来未来
  19. 计算机特定用户共享文件夹,局域网共享给特定用户、文件夹共享给指定用户访问方法...
  20. Unity3D 使用图片自定义字体,防止打包安卓后字体变形

热门文章

  1. 2018第17周总结
  2. android通过Canvas和Paint截取无锯齿圆形图片
  3. 【Docker容器】进入容器的2种方式
  4. 图像处理里面的的尺度什么?
  5. redis演练(1) 搭建redis服务
  6. ASP.NET或者 js方式实现文件夹多图片浏览的方式
  7. 腾讯惹谁了?为什么用QQ邮箱投简历不受人待见
  8. java修改request的paramMap
  9. AndroidGUI24:TabHost常用技巧
  10. 使用移远EC200N-CN模组PING谷歌