产生的DLL (VS2005, MATLAB7.5, mwArray)
| from:?http://www.simwe.com/forum/thread-801187-1-1.html 程序中使用MATLAB編譯產生的DLL (VS2005, MATLAB7.5, mwArray) 最近有幾個帖子都在討論有關在C++程序中使用MATLAB編譯產生的動態鏈接庫DLL。本 來想用原來帖子中給出的m代碼作為例子,無奈那段代碼其實無法執行。為了避免分散注意力,也為了更好地討論問題,于是決定還是另外新開一個主題,以簡單的 例子,和大家一起討論如何在C++程序中使用matlab編譯產生的DLL。 同時MATLAB最新版本R2007b剛剛發布不久,其中包含編譯器4.7版,有了一些新的特性,于是也借這個例子來驗證一下相關的技術有沒有發生大的變化。 最近討論的問題是關于在C++程序中調用MATLAB編譯產生的動態鏈接庫。具體的問題是在 調用DLL中函數時傳遞參數。我們知道,MATLAB可以把m代碼編譯成兩種DLL,分別是C語言接口和C++語言接口的DLL。論壇上的問題是關于調用 C++接口的DLL中的函數,所以這里我們就以這種DLL為例來介紹。在C++接口的DLL中,函數的輸入、輸出參數都是mwArray對象。所以問題歸 結為如何在C++程序中使用mwArray。 這個問題本來可以只用一個簡單的C++程序來練習,而不需要MATLAB編譯的DLL。不過為了模擬實際情況,選擇以一個更為接近實際的m代碼作為例子。在這個例子中,輸入輸出都是矩陣,至于標量,它也是一個一行、一列的矩陣。 實驗環境:Windows 2003 Std Server with SP2 (En),MATLAB R2007b,Visual Studio 2005。MATLAB安裝路徑:h:MATLABR2007b。 實驗內容:把一個簡單的m代碼編譯成C++接口的DLL,然后在C++程序中調用。為了簡單起見,這里的C++程序是一個Win32 Console程序,而不是Windows圖形界面的程序,不過不妨礙我們的討論。 下面是這個例子用到的m代碼。它定義了一個名為myadd2的函數: [Copy to clipboard]?[ - ] CODE: function [y,z] = myadd2(a, b) % dummy function, just to demonstrate the idea y = a+b; z = a+2*b; end 首先把這個函數編譯成C++接口的DLL。為此,我們需要先設置MATLAB編譯器。具體做法是在MATLAB命令行執行“mbuild -setup”。然后用下面這行命令把myadd2函數編譯成一個C++接口的DLL: [Copy to clipboard]?[ - ] CODE: mcc -W cpplib:libmyadd2 -T link:lib myadd2 結果,我們將會得到包含libmyadd2.dll,libmyadd2.ctf,libmyadd2.h,libmyadd2.lib等在內的一些文件。接下來我們只需要這四個文件。請注意:在MATLAB R2007b之前,這些文件都會在和編譯 的m代碼所在的目錄中,而在MATLAB R2007b,缺省情況下這些文件會在Documents and Settings中用戶的My Documents目錄中。 此時,打開libmyadd2.h看看,在文件的最下面我們可以發現C++接口的函數定義。仔細觀察過后,我們可以發現,這個接口函數的參數是按照這樣的順序定義的:輸出參數的個數、輸出參數、以及輸入參數。 然后在VS2005中創建一個Win32 Console的VC++工程,我在測試時取名為testmyadd2_r2007b。把以上四個文件拷貝到VC++工程的源代碼所在目錄。 接下來設置VC++,讓它能找到MATLAB接口函數的定義及連接庫函數。可以有兩種設置方式:一種是改VS2005中關于VC++的設置,這樣的好處是每個新的工程都能自動獲得這個設定;而另一種是只改當前工程的設置,也就是設置只對該工程有效。這里用后一種方式。 在VS2005中打開工程testmyadd2_r2007b,選擇菜單“Project-->Properties,在出來的對話框上,把MATLAB提供的include路徑加到VC++的頭文件搜索路徑。如圖所示: ? ?vs2005_matlabr2007b_inc01.gif?(25.26 KB) ? 然后把相應的lib所在目錄加到linker的額外搜索路徑上。如圖所示: ?vs2005_matlabr2007b_lib01.gif?(25.99 KB)?接下來,告訴VC++,我們的這個程序需要連接到另外兩個額外的庫函數:libmyadd2.lib和mclmcrrt.lib。中間用空格隔開。如圖所示: ?vs2005_matlabr2007b_lib02.gif?(23.16 KB)? 最后則是程序代碼。這個程序只有一個main函數,其完整代碼附在下面給大家參考。歡迎大家拍磚。謝謝! CODE: #include "stdafx.h" #include? #include "mclmcr.h" #include "mclcppclass.h" #include "libmyadd2.h" int _tmain(int argc, _TCHAR* argv[]) { ?? ??? std::cout << "Hello world!" << std::endl; ?? ??? /* Initialize the MCR */? ?? ??? if( !mclInitializeApplication(NULL,0) )? ?? ??? {? ?? ?? ?? ?? std::cout << "Could not initialize the application!" << std::endl; ?? ?? ?? ?? return -1;? ?? ??? }? ?? ??? // initialize lib ?? ??? if( !libmyadd2Initialize()) ?? ??? { ?? ?? ?? ?? std::cout << "Could not initialize libmyadd2!" << std::endl; ?? ?? ?? ?? return -1;? ?? ??? } ?? ??? try ?? ??? { ?? ??? // declare and initialize a ?? ??? mwArray a(2, 2,?? mxDOUBLE_CLASS); ?? ??? double *aData; ?? ??? aData = new double[4]; ?? ??? int i; ?? ??? for( i=0; i<4; ++i) ?? ??? { ?? ?? ?? ?? aData[i] = 1.0*i; ?? ??? } ?? ??? // print output ?? ??? std::cout << "a = " << std::endl; ?? ??? std::cout << aData[0] << ", " << aData[1] << std::endl; ?? ??? std::cout << aData[2] << ", " << aData[3] << std::endl; ?? ??? a.SetData(aData, 4); ?? ??? // declare and initialize b ?? ??? mwArray b(2, 2,?? mxDOUBLE_CLASS); ?? ??? b(1,1) = 11.; ?? ??? b(1,2) = 12.; ?? ??? b(2,1) = 21.; ?? ??? b(2,2) = 22.; ?? ??? mwArray y(2, 2,?? mxDOUBLE_CLASS); ?? ??? mwArray z(2, 2,?? mxDOUBLE_CLASS); ?? ??? // call the function ?? ?? ?? ?? myadd2(2, y, z, a, b); ?? ??? // copy data from mwArray to C++ objects ?? ??? // allocate outputs ?? ??? double *yData, *zData; ?? ??? yData = new double[4]; ?? ??? if( yData == NULL ) ?? ??? { ?? ?? ?? ?? std::cout << "Failed to allocate memory for yData!" << std::endl; ?? ?? ?? ?? return -1; ?? ??? } ?? ??? zData = new double[4]; ?? ??? if( zData == NULL ) ?? ??? { ?? ?? ?? ?? std::cout << "Failed to allocate memory for zData!" << std::endl; ?? ?? ?? ?? return -1; ?? ??? } ?? ??? // copy data from mwArray to C++ ?? ??? y.GetData(yData, 4); ?? ??? z.GetData(zData, 4); ?? ??? // print output ?? ??? std::cout << "y = " << std::endl; ?? ??? std::cout << yData[0] << ", " << yData[1] << std::endl; ?? ??? std::cout << yData[2] << ", " << yData[3] << std::endl; ?? ??? std::cout << "z = " << std::endl; ?? ??? std::cout << zData[0] << ", " << zData[1] << std::endl; ?? ??? std::cout << zData[2] << ", " << zData[3] << std::endl; ?? ??? ?? ??? // deallocate memory ?? ??? delete [] aData; ?? ??? delete [] zData; ?? ??? delete [] yData; ?? ??? } ?? ??? catch( const mwException& e) ?? ??? { ?? ?? std::cerr << e.what() << std::endl; ?? ?? ?? ?? ??? ?? ??? } ?? ??? // terminate the lib ?? ??? libmyadd2Terminate(); ?? ??? // terminate MCR ?? ??? mclTerminateApplication(); ?? ??? return 0; } 2007-10-6 23:18 ?vs2005_matlabr2007b_result.gif?(9.26 KB)? 實驗的結果表明,在C++程序中使用MATLAB編譯產生的C++接口DLL非常容易。 mwArray也很容易使用。另外,最新的MATLAB R2007b中關于這部分并沒有什么大的變化。這個練習適合MATLAB 7.0以后直到MATLAB R2007b的所有版本。 ask: 就我個人6.5混編的經驗,我很少弄DLL,直接編譯M文件為cpp,h文件即可,VC工程中引用,按.h文件格式調用即可。 這樣混編基本沒有任何難度,將MATLAB程序看成MFC一個類即可,看看extern里面 相關頭文件的定義,跟看MSDN一樣。 拋開mclTerminateApplication();這些,這應該是一個通用的辦法 手頭只有6.5,不知道7.5還能生成cpp么? answer: 從matlab7.0開始,其編譯器的功能就和以前版本不一樣了。它不再把m代碼翻譯成C/C++源代碼,而是對m代碼作個簡單的 wrapper,通常以動態鏈接庫的形式提供給用戶以方便用戶在其他的程序中使用。所以,在matlab 7.x,編譯m代碼不能得到以前那種意義的C/C++源程序。不過,僅從軟件開發的角度來看,我覺得用DLL來打包更為方便。如果m函數的接口不變,那么每次改變m代碼后,我們只需重新編譯m代碼,獲得新的DLL及CTF,而不需要重新編譯VC客戶程序。這在開發大型軟件時有很大的優越性。 多謝taohe的文章,我想問一下,ctf文件是干嘛用的,謝謝,記得matlab 6.5版里面編譯為DLL時沒這個東西啊。 這是matlab7.0以后matlab編譯器的新特性。它和舊版技術不兼容。ctf其實就是一個zip文件,其中包含加密或者說編碼過的一些m代碼。其中有你自己的代碼,以及matlab編譯器通過分析你的代碼根據依賴關系找到的其他一些m代碼。 |
轉載于:https://www.cnblogs.com/mfryf/archive/2012/02/16/2354285.html
總結
以上是生活随笔為你收集整理的产生的DLL (VS2005, MATLAB7.5, mwArray)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Direct3D学习_绘制
- 下一篇: 简单代码生成器原理剖析(一)