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

 最近的项目须要matlab和C的混合编程,通过一番努力终于完成了项目要解决的问题。如今就将Mex的一些经验总结一下,固然只是刚刚开始,之后随着学习的深刻继续添加。首先讲讲写Mex的一些常规规定,而后咱们会重点关注混合编程中最难解决数据的问题--结构到底如何转换,而且后面会重点说一下本身的程序。html

1、Mex的结构c++

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#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(); 返回值如上。缓存


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

(1)数值的传递函数

matlab -> c++学习

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

 c++ -> matlabspa

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

一个实例(numDemon.cpp):指针

1
2
3
4
5
6
7
8
9
10
11
#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++,看下面这段代码:

如:matlab传进来的矩阵为与指针访问的顺序对应

0  3  6  9

1  4  7  10

2  5  6  11

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#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++ (传入)

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

 c++ -> matlab (传出)

1
2
3
4
5
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)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#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的传入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#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

 感谢http://www.cnblogs.com/Key-Ky/p/4233581.html

相关文章
相关标签/搜索