我的最初想法是利用matlab的mex命令調用C++程序生成動態鏈接庫的,但是測試程序(文中另附)通過了,自己的實際應用程序卻沒有過。還是把方法貼在這兒,以便自己以后進行整理。
http://shijuanfeng.blogbus.com/logs/106781870.html
以下內容來自上面博客,自己根據實際情況略作解釋改動。
- MATLAB要調用C++程序步驟:
1. 在MATLAB命令行敲:mex -setup,選擇你所使用的C++版本,裝上mex(參考下面“2.MATLAB設置”)
2. 用“mex [參數] *.cpp”, eg:mex -O -c svm.cpp
這時在當前目錄下就會生成*.mexw32,*.mexw64的文件,這個文件類似於c++的dll文件,MATLAB可以直接調用。
當前,上述的cpp文件不是我們平時所寫的以main函數為入口,而是是mexFunction函數為入口,當然,還有其他不同,以下會進一步說明。
Mex文件的產生和調試(版本:VC++6.0和MATLAB7.0)
1 、 VC++6.0 環境及工程設置
在上面的 VC 工程中,進行以下設置
(1) VC++6.0 環境設置
單擊菜單 Tools ,單擊 Options… 菜單項,出現 Options 對話框,選擇 Directories 標簽,在 include files 里面加入:
C:\MATLAB6P5\EXTERN\INCLUDE(就是你自己的matlab安裝路徑)
在 Library files 里面加入:
C:\MATLAB6P5\EXTERN\LIB\WIN32\MICROSOFT\MSVC60
2) VC++6.0 工程設置
單擊菜單 Project ,單擊 Setting… 菜單項,出現 Project Setting 對話框,選擇 Link 標簽,在 Object/library modules: 下面的文本框內容的后面加入 libmx.lib libmex.lib libmat.lib
設置完成。
2.MATLAB設置:
(1) mex 命令設置
(a) 運行 Matlab ,在 Matlab 的命令窗口 (Command Window) 鍵入“ mex -setup ”命令后,按回車鍵,安裝 Matlab 編譯器;
(b) 命令窗口出現如下提示:
Please choose your compiler for building external interface (MEX) files:
Would you like mex to locate installed compilers [y]/n?
此時鍵入 ”y” ,按回車;
(c) 命令窗口出現如下提示:
Please choose your compiler for building external interface (MEX) files:
Would you like mex to locate installed compilers [y]/n? y
Select a compiler:
[1] Digital Visual Fortran version 6.0 in C:\Program Files\Microsoft Visual Studio
[2] Lcc C version 2.4 in C:\MATLAB6P5\sys\lcc
[3] Microsoft Visual C/C++ version 6.0 in C:\Program Files\Microsoft Visual Studio
[0] None
此時鍵入 ” 3” ,按回車;選擇 Microsoft Visual C++6.0 的編譯器
(d) 命令窗口出現如下提示:
Please verify your choices:
Compiler: Microsoft Visual C/C++ 6.0
Location: C:\Program Files\Microsoft Visual Studio
Are these correct?([y]/n):
此時鍵入 ”y” ,按回車;確認選擇 Microsoft Visual C++6.0 的編譯器
(3) mbuild 命令設置
(a) 運行 Matlab ,在 Matlab 的命令窗口 (Command Window) 鍵入“ mbuild -setup ”命令后,按回車鍵,安裝 Matlab 編譯器;
(b) 命令窗口出現如下提示:
Please choose your compiler for building standalone MATLAB applications:
Would you like mbuild to locate installed compilers [y]/n?
此時鍵入 ”y” ,按回車;
(c) 命令窗口出現如下提示:
[1] Lcc C version 2.4 in C:\MATLAB6P5\sys\lcc
[2] Microsoft Visual C/C++ version 6.0 in C:\Program Files\Microsoft Visual Studio
[0] None
此時鍵入 ” 2” ,按回車;選擇 Microsoft Visual C++6.0 的編譯器
(d) 命令窗口出現如下提示:
Please verify your choices:
Compiler: Microsoft Visual C/C++ 6.0
Location: C:\Program Files\Microsoft Visual Studio
Are these correct?([y]/n):
此時鍵入 ”y” ,按回車;確認選擇 Microsoft Visual C++6.0 的編譯器
(4) 在 Matlab 的命令窗口 (Command Window) 鍵入cd(prefdir); savepath prefdir;就可以了,其他版本未知。
3.添加 mexFunction 函數代碼
http://blog.sina.com.cn/s/blog_715d0ae30100rtd5.html
這部分參考的是以上博客的代碼,解釋的很清楚
1、函數的形式必須是
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
nlhs:輸出參數個數 plhs:輸出參數列表 nrhs:輸入參數個數 prhs:輸入參數列表
不過函數名可以隨便取的。注意:保存的文件名就是將來在MATLAB中調用的函數名,而不是這里的函數名。
下面給出一個例子,目的是想截取數組的部分元素組成新的數組
輸入參數3個,目標數組,截取的行(向量),截取的列(向量) 輸出參數2個,截取后數組,數組維數信息
在函數中展示了如何傳入傳出參數,以及如果從參數列表中取出每一個參數,MATLAB數據和C++數據的互相轉換,還有一些輸出函數等。
新建一個ResizeArray.cpp文件(ResizeArray將作為MATLAB調用的函數名),寫入下面代碼
#include "mex.h" //author: 汪幫主 2010.05.05 //MATLAB調用形式: [resizedArr, resizedDims] = ResizeArray(arr, selRows, sekCols) void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { if (nrhs != 3) { mexErrMsgTxt("參數個數不正確!"); } int rowNum = mxGetM(prhs[0]); int colNum = mxGetN(prhs[0]); double* pArr = (double*)mxGetPr(prhs[0]); //得到選擇的行列信息 //無論是行向量還是列向量均支持 double* pSelRows = (double*)mxGetPr(prhs[1]); double* pSelCols = (double*)mxGetPr(prhs[2]); int selRowsRowNum = mxGetM(prhs[1]); int selRowsColNum = mxGetN(prhs[1]); if (selRowsRowNum!=1 && selRowsColNum!=1) { mexErrMsgTxt("行參數不正確!"); } int selRowsNum = selRowsRowNum*selRowsColNum; int selColsRowNum = mxGetM(prhs[2]); int selColsColNum = mxGetN(prhs[2]); if (selColsRowNum!=1 && selColsColNum!=1) { mexErrMsgTxt("列參數不正確!"); } int selColsNum = selColsRowNum*selColsColNum; plhs[1] = mxCreateDoubleMatrix(2, 1, mxREAL); double* resizedDims = (double*)mxGetPr(plhs[1]); resizedDims[0] = selRowsNum; resizedDims[1] = selColsNum; plhs[0] = mxCreateDoubleMatrix(selRowsNum, selColsNum, mxREAL); double* pResizedArr =(double*)mxGetPr(plhs[0]); //這里因為MATLAB中數據得按列優先 #define ARR(row,col) pArr[(col)*rowNum+row] #define RARR(row,col) pResizedArr[(col)*selRowsNum+row] for(int ri=0; ri<selRowsNum; ri++) { for(int ci=0; ci<selColsNum; ci++) { RARR(ri,ci)=ARR((int)pSelRows[ri]-1,(int)pSelCols[ci]-1); } } mexPrintf("OK!\n"); }
2、編譯C++函數為MEX函數
將ResizeArray.cpp放在MATLAB當前目錄中,在MATLAB中輸入mex ResizeArray.cpp,編譯成功后將會生成ResizeArray.mexW32
3、在matlab中調用函數
arr=[11:19;21:29;31:39;41:49;51:59;61:69]; selRows=[1 3]; selCols=[2:4 5 9]; [rarr,rdims]=ResizeArray(arr,selRows,selCols)
4、運行結果
rarr = 12 13 14 15 19 32 33 34 35 39 rdims = 2 5
運行成功!!
這部分參考的是一篇博客的內容,經證實是可行的。
附上源博客地址:http://hi.baidu.com/welcomeclark/item/ff333321af845f8a6f2cc3c0
我自己的實驗結果:
1.設置Visual C++6.0編譯環境,添加相應的頭文件和庫文件的路徑。打開菜單->工具->選項。
2.設置系統的環境變量path,添加E:\program\MATLAB\bin\win32(注:這一部分可不用添加,一般安裝matlab程序的時候,是設置好了的)
3.創建Win32 Dynamic-Link Library工程實現mex文件。
4.創建CPP文件。 (這里就是你要實現的函數主體部分)
5.向工程添加DEF文件
添加內容:
LIBRARY "mexdemo1"
EXPORTS
mexFunction @1
6.設置工程,鏈接中對象/庫模塊添加libmx.lib libmat.lib libmex.lib。
7.設置動態庫的調試路徑。
在調試中添加E:\program\MATLAB\bin\win32\MATLAB.exe
8.調試程序。使用快捷鍵F5或go圖標。彈出對話框
在Matlab中輸入如下命令,就可以進行程序調試。
注:cd 指的是定位到某個文件夾,接下來就是在matlab中調用函數的命令,根據具體函數名而定。
還可以在 mexFunction 源程序中合適的設置斷點,然后按 F5 鍵進入調試過程 。在 Matlab 命令窗口調用 **.dll ,程序就會停在 VC++6.0 環境里的程序斷點處。此時可以 在 Context 窗口中看到最近處理的變量數值 ,並可以 隨意添加 Watch 。這樣就可以像調試通常的 C 程序一樣對 mex 程序進行調試。
注意:若出現LINK : fatal error LNK1104: cannot open file "libmx.lib"問題,請檢查庫文件是否正確添加。
在前面一篇文章Visual C++ 6.0與matlab聯合編程(2)中,利用VC++生成了DLL文件,但是一般matlab命令生成的DLL文件名后綴為mexw32,我們可以利用def文件導出mexFunction函數。這里,我參考了另一篇博客,但是他的環境是2008,在VC6.0里設置也很簡單。
在上面的Output file name中將輸出文件的后綴名改為mexw32就可以了。