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

最近的项目需要matlab和C的混合编程,经过一番努力终于完成了项目要解决的问题。现在就将Mex的一些经验总结一下,当然只是刚刚开始,以后随着学习的深入继续添加。首先讲讲写Mex的一些常规规定,然后我们会重点关注混合编程中最难解决数据的问题--结构到底如何转换,并且后面会重点说一下自己的程序。

一、Mex的结构

先看一个简单的程序(该程序保存在matlab主目录下名字是mexDemon.cpp,或者在主目录下新建一个.cpp文件):

#include "mex.h"  

//加入头文件,该头文件在VS2010中无法include,但是不影响其在matlab中的编译,反而在matlab编译还需要include它

#include <vector>

using namespace std;

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

//mexFunction就类似于main函数

{

    //nlhs代表的是输出参数的个数

    //plhs是一个指针数组,里面的指针指向mxArray类型,每一个指针指向一个输出

    //nrhs代表的是输入参数的个数

    //prhs是一个指针数组,里面的指针指向mxArray类型,每一个指针指向一个输入

  vector<vector<double> > array2d;

    double *z;

    plhs[0] = mxCreateDoubleMatrix( 5, 6, mxREAL);//第一个输出是一个5*6的矩阵

    z = mxGetPr(plhs[0]);//获得矩阵的第一个元素的指针

    array2d.resize(5);

    int ii = 0;

    for(int i = 0; i < 5; i++){

        for(int j = 0; j < 6; j++){

            z[i*6 + j] = ii; //指针访问矩阵是列优先的,请自己循环程序和分析输出结果

            ii++;

        }

    }

}  

/*

 *ans =

     0     5    10    15    20    25

     1     6    11    16    21    26

     2     7    12    17    22    27

     3     8    13    18    23    28

     4     9    14    19    24    29

 */

  

然后对Matlab编译应用程序mex的编译器进行设置,在命令窗口输入 Mex –setup。 然后跟着步骤走选择合适的编译器即可。

设置完编译器之后在命令窗口输入Mex mexDemon.cpp 进行编译生成.mexw64文件,生成之后便可以直接调用了,例如本例子可以这样调用,就是直接在命令窗口输入 a = mexDemon(); 返回值如上。


二、C和Matlab的数据结构的转换

(1)数值的传递

matlab -> c++

x = mxGetScalar(prhs[0]);//该函数获取matlab传递过来的数值;

c++ -> matlab

plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);//创建返回的矩阵,范围plhs[0]为mxArray类型
y = mxGetPr(plhs[0]);//获取返回plhs[0]的数据地址,其后可以修改y的值就可以返回了

一个实例(numDemon.cpp):

#include "mex.h"

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

    int x = mxGetScalar(prhs[0]); //将第一个输入参数转为Scalar标量,也就是单数值

    printf("%d\n", x); //打印

    double *y; 

    plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL); //让第一个输出参数指向一个1*1的矩阵

    y = mxGetPr(plhs[0]); //获得矩阵的第一个元素的指针

    *y = 10; //将其赋值为10

}

  

如下图在命令窗口编译:


(2)矩阵的传入与传出

关于传出(c++到Matlab, 就是第一个例子),下面可以再给一个例子是如何从matlab传入到c++,看下面这段代码:

#include "mex.h"

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

    double *dataCursor;

    vector<vector<double> > parms;

    dataCursor = mxGetPr(prhs[0]); //得到输入矩阵的第一个元素的指针

    int mrows = mxGetM(prhs[0]);   //获得矩阵的行

    int ncols = mxGetN(prhs[0]);   //获得矩阵的列

    printf("%d_%d\n", mrows, ncols);  //打印行和列

    parms.resize(mrows);  //初始化

    for(int i = 0; i < mrows; i++){

        parms[i].resize(ncols);

    }

    for(int i = 0; i < mrows; i++){

        for(int j = 0; j < ncols; j++){

            parms[i][j] = dataCursor[j * mrows + i]; //拷贝矩阵的元素到vector of vector

        }

    }

} 

同样在命令窗口编译即可。


(3)字符串的传入与传出

matlab -> c++ (传入)

char *input_buf;

input_buf = mxArrayToString(prhs[0]);//使用mxArrayToString将mxArray转换为c、c++字符串

c++ -> matlab (传出)

char *output_buf;//定义字符串缓存

size_t buflen = (mxGetM(prhs[0]) * mxGetN(prhs[0])) + 1;//获取字符串长度,mxGetM获取行数,mxGetN获取列数

output_buf=mxCalloc(buflen, sizeof(char));//使用mxCalloc分配输出字符串数组

plhs[0] = mxCreateString(output_buf);//使用mxCreateString创建mxArray输出

mxfree(output_buf);

一个实例(strDemon.cpp)

#include "mex.h"

void revord(char *input_buf, size_t buflen, char *output_buf)

{

  mwSize i;

  if (buflen == 0) return;

  for(i=0;i<buflen-1;i++)

    *(output_buf+i) = *(input_buf+buflen-i-2);

}

void mexFunction( int nlhs, mxArray *plhs[],

                  int nrhs, const mxArray *prhs[])

{

    char *input_buf, *output_buf;

    size_t buflen;

    buflen = (mxGetM(prhs[0]) * mxGetN(prhs[0])) + 1; //因为本程序是翻转字符串,所以输入输出字符串的长度应该一样

    output_buf=mxCalloc(buflen, sizeof(char)); //申请空间

    input_buf = mxArrayToString(prhs[0]); //获得输入字符串

    revord(input_buf, buflen, output_buf); //翻转字符串

    plhs[0] = mxCreateString(output_buf); 

    mxFree(input_buf);

    return;

}

  

同样编译一下即可。


(4)cell的传入

#include "mex.h"

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

    mwSize cellNdim = mxGetNumberOfDimensions(prhs[0]); //这里介绍两个函数mxGetNumberOfDimensions和mxGetDimensions

    const int *cellColPtr = mxGetDimensions(prhs[0]);

    //mxGetDimensions: 就是返回一个指针ptr,每一个指针所指向的值是每一个维度的元素个数。例如有矩阵3*2的矩阵,那么*(ptr)为3,*(ptr+1)为2.

    //mxGetNumberOfDimensions: 返回mxArray的维度。

    int cellNRow = *(label_dims);

    int cellNCol = *(label_dims + 1);

    mxArray *ptr;

    ptr = mxGetCell(prhs[0], 0); //获取cell的第0个元素,返回一个mxArray指针,第二个参数代表cell中元素的下标

    mxArray *cellOfCell;

    cellOfCell = mxGetCell(ptr, 0);    //当然cell里面可以还是cell,那么应该再样写

    mxArray *cellOfStr;

    char *chTmp;

    cellOfStr = mxGetCell(prhs[0], 0); //当然cell里面可以是字符串

    chTmp = mxArrayToString(cellOfStr);

    printf("%s\n", chTmp);

}

  

后面待补充结构体和cell数组的传出,暂时还没遇到这样的需求。再贴上几个参考网址:

1.http://blog.sina.com.cn/s/blog_9db9f81901013yv2.html

2.http://blog.sina.com.cn/s/blog_80202a090100uhup.html

matlab和C/C++混合编程--Mex (转载)的更多相关文章

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

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

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

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

  3. 【5.1送礼】国内第一部Matlab和C#.Net混合编程视频教程【免费】

                  本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新    Matlab和C#混合编程文章目录 :[目录]Matlab和C#混合编程文章目录 上一次写博客很久了 ...

  4. matlab和C/C++混合编程--调用opencv

    最近的我们已经将整个项目搭起来了,项目比较复杂.由于我们做的是检索系统,所以我们用asp.net(c#)做了网页,但是算法的实现是在matlab下,所以我们不得不用matlab生成动态链接库dll,然 ...

  5. matlab + c/c++ opencv 混合编程

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 辛苦原创所得,转载请注明出处 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ...

  6. MATLAB与C/C++混合编程的一些总结

    [转载请注明出处]http://www.cnblogs.com/mashiqi 先上总结: 由于C/C++语言的函数输入输出参数的特点,可以将多个参数方便地传入一个函数中,但却不能方便地返回多个参数. ...

  7. Matlab和C语言混合编程,包含目录的设定

    如果.c文件不依赖于任何第三方库,那么mex编译很简单,只需要在matlab的命令行输入 mex test.c 即可. 但是如果这个c文件使用了第三方库文件,如opencv.gsl等等,那么就需要更改 ...

  8. MATLAB和C语言混合编程-----Matlab7.0 编译器设置

    (1) mex 命令设置 (a) 运行 Matlab ,在 Matlab 的命令窗口 (Command Window) 键入“ mex -setup ”命令后,按回车键,安装 Matlab 编译器: ...

  9. Matlab 2013a 和 VS2010 混合编程

    最近由于项目需求,某项目的算法是基于MATLAB完成的,在短时间内需要去调用算法功能.因此,基于MATLAB生成DLL, C 调用的方式完成. 环境:MATLAB 2013a + VS2010 + w ...

随机推荐

  1. Oracle判断两个时间段是否相交

    SQL中常常要判断两个时间段是否相交,该如何判断呢?比如两个时间段(S1,E1)和(S2,E2).我最先想到的是下面的方法一.方法一:(S1 BETWEEN S2 AND E2) OR (S2 BET ...

  2. Because, since, as, for

    because, as, for, since这几个词都是表示“原因”的连词,语气由强至弱依次为:because→since→as→for;其中because, since, as均为从属连词,引导原 ...

  3. Razor - 模板引擎 / 代码生成 - RazorEngine

    目录 Brief Authors Official Website RazorEngine 的原理 - 官方解释 安装记录 Supported Syntax (默认实现支持的语法) 测试记录 - ca ...

  4. 教你用 google-drive-ocamlfuse 在 Linux 上挂载 Google Drive

    如果你在找一个方便的方式在 Linux 机器上挂载你的 Google Drive 文件夹, Jack Wallen 将教你怎么使用 google-drive-ocamlfuse 来挂载 Google ...

  5. Visual Studio Image Library

    The Visual Studio Image Library Visual Studio 2013   The Visual Studio Image Library contains applic ...

  6. poj 2236 Wireless Network 【并查集】

    Wireless Network Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 16832   Accepted: 706 ...

  7. asp.net页面生命周期之页面的终结阶段

    处理过回发事件之后,页面便为浏览器生成输出做好了准备.呈现阶段分为两部分:预呈现和标记生成.预呈现这个子阶段有两个事件表征,分别为:预处理和投递处理. PreRender事件 通过处理该事件,页面和控 ...

  8. iOS 使用NSUserdefault 保存自定义的 对象

    一:NSUserDefaults支持的数据格式有:NSNumber(Integer.Float.Double),NSString,NSData,NSArray,NSDictionary,BOOL类型: ...

  9. mysql 创建函数或者存储过程,定义变量报错

    报错的原因是因为在过程或者函数中存在分隔符 分号(:),而mysql中默认分隔符也是 :,这就导致存储过程分开了 在存储过程外面包一层 delimiter //   code  //就行了

  10. [Spring MVC - 2A] - java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)

    严重: Servlet.service() for servlet [springMVC] in context with path [/ExceptionManageSystem] threw ex ...