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

相關文章
相關標籤/搜索