最近的項目須要matlab和C的混合編程,通過一番努力終於完成了項目要解決的問題。如今就將Mex的一些經驗總結一下,固然只是剛剛開始,之後隨着學習的深刻繼續添加。首先講講寫Mex的一些常規規定,而後咱們會重點關注混合編程中最難解決數據的問題--結構到底如何轉換,而且後面會重點說一下本身的程序。html
1、Mex的結構c++
先看一個簡單的程序(該程序保存在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(); 返回值如上。緩存
2、C和Matlab的數據結構的轉換數據結構
(1)數值的傳遞函數
matlab -> c++學習
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):指針
#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