凡兄弟 發表於 2005-11-9 14:30:32
VC + MATLAB7 C Shared Library
所有調用MATLAB7 Compiler產生的共用庫的程式都具有如下的大致結構:
1. 聲明變數或者是函數作為輸入變數;
2. 調用 mclInitalizeApplication函數,並測試是否成功,該函數設定了一個全域的MCR狀態,並且構建MCR執行個體;
3. 對於每個庫,調用一次<libraryname>Initalize函數,為庫建立一個MCR執行個體;
4. 調用庫中的函數,並處理其結果(這是程式的主要部分);
5. 為每個庫調用一次<libraryname>Terminate函數,用於登出相聯絡的MCR;
6. 調用mclTerminateApplication函數,釋放與全域MCR狀態相聯絡的資源;
7. 清除變換,關閉檔案等,然後退出。
根據MATLAB的協助文檔中提供的例子,利用如下檔案進行練習:
<matlabroot>/extern/examples/compiler/addmatrix.m
<matlabroot>/extern/examples/compiler/multiplymatrix.m
<matlabroot>/extern/examples/compiler/eigmatrix.m
實現步驟:
1) 先將這幾個檔案拷貝到目前的目錄下,然後利用mcc建立共用庫,指令如下:
mcc –v -B csharedlib:libmatrix addmatrix.m multiplymatrix.m eigmatrix.m
其中,巨集指令引數 -B csharedlib 是一個綁定的操作,其等效指令為 -W lib:<libname> -T link:lib。
2)在VC中建立一個MFC工程(本人建立的為基於對話方塊的),環境設定根據如下文章:
怎樣設定 Visual Studio 與 Matlb Complier 4.0 一起工作 中的指導進行。在本例子中,只需要在VC中進行如下步驟:
A. Tools->Options->Directories->Show directories for:Include files-><matlab7root> \Extern\Include;
B. Tools->Options->Directories->Show directories for:Library files-><matlab7root> \Extern\Lib\Win32\Microsoft\msvc60;
C. Project->Setting->C/C++->Category:Code Generation->Use run-time library:Debug Multithread DLL;
D. Project->Setting->Link->Category:Input->Object/library modules:mclmcrrt.lib libmatrix.lib(mcc產生的共用庫)。
3)拷貝MATLAB目前的目錄下剛才用mcc產生的libmatrix.h,libmatrix.dll,libmatrix.lib,以及 libmatrix.ctf檔案到VC當前工程目錄下,並用Project->Add to Project->Files…將libmatrix.h加入到當前工程中。
4)在當前工程的對話方塊的標頭檔中加入#include "libmatrix.h" 與 #include "mclmcr.h";
5)在BOOL CMatlab7dllDlg::OnInitDialog()中進行MATLAB庫檔案的初始化,在void CMatlab7dllDlg::OnDestroy()中進行MATLAB庫檔案資源的釋放,否則可能出現按鈕只能夠按一次,第二次運行則出錯的現象;
6)調用MATLAB產生的庫檔案中函數的處理函數定義在一個按鈕的響應函數中,並且要注意的是:如果一個mxArray變數需要重用的時候,必須用mxDestroyArray(out); out=0;即先進行變數登出,再設定為空白。
附上這幾個主要函數如下:
1.BOOL CMatlab7dllDlg::OnInitDialog()
{
CDialog::OnInitDialog();
……………
// TODO: Add extra initialization here
/* Call the mclInitializeApplication routine. Make sure that the application
* was initialized properly by checking the return status. This initialization
* has to be done before calling any MATLAB API's or MATLAB Compiler generated
* shared library functions. */
if( !mclInitializeApplication(NULL,0) )
{
AfxMessageBox( "Could not initialize the application.");
exit(1);
}
/* Call the library intialization routine and make sure that the
* library was initialized properly. */
if (!libmatrixInitialize())
{
AfxMessageBox("Could not initialize the library.");
exit(1);
}
return TRUE; // return TRUE unless you set the focus to a control
}
2.void CMatlab7dllDlg::OnDestroy()
{
CDialog::OnDestroy();
/* Call the library termination routine */
libmatrixTerminate();
mclTerminateApplication();
}
3.void CMatlab7dllDlg::OnRUN()
{
CString str;
mxArray *in1, *in2; /* Define input parameters */
mxArray *out = NULL;/* and output parameters to be passed to the library functions */
double data[] = {1,2,3,4,5,6,7,8,9};
/* Create the input data */
in1 = mxCreateDoubleMatrix(3,3,mxREAL);
in2 = mxCreateDoubleMatrix(3,3,mxREAL);
memcpy(mxGetPr(in1), data, 9*sizeof(double));
memcpy(mxGetPr(in2), data, 9*sizeof(double));
/* Call the library function */
mlfAddmatrix(1, &out, in1, in2);
/* Display the return value of the library function */
str="The value of added matrix is:\n";
str = str + Display(out);
AfxMessageBox(str);
/* Destroy the return value since this varaible will be resued in
* the next function call. Since we are going to reuse the variable,
* we have to set it to NULL. Refer to MATLAB Compiler documentation
* for more information on this. */
mxDestroyArray(out); out=0;
mlfMultiplymatrix(1, &out, in1, in2);
str = "The value of the multiplied matrix is:\n";
str = str+Display(out);
AfxMessageBox(str);
mxDestroyArray(out); out=0;
mlfEigmatrix(1, &out, in1);
str = "The Eigen value of the first matrix is:\n";
str = str+Display(out);
AfxMessageBox(str);
mxDestroyArray(out); out=0;
/* Free the memory created */
mxDestroyArray(in1); in1=0;
mxDestroyArray(in2); in2 = 0;
AfxMessageBox("OK, Finished!");
}
4.CString CMatlab7dllDlg::Display(const mxArray *in)
{
CString str, strout=" ";
int i=0, j=0; /* loop index variables */
int r=0, c=0; /* variables to store the row and column length of the matrix */
double *data; /* variable to point to the double data stored within the mxArray */
/* Get the size of the matrix */
r = mxGetM(in);
c = mxGetN(in);
/* Get a pointer to the double data in mxArray */
data = mxGetPr(in);
/* Loop through the data and display the same in matrix format */
for( i = 0; i < c; i++ ){
for( j = 0; j < r; j++){
str.Format("%4.2f\t",data[i*c+j]);
strout = strout+str;
}
strout = strout+"\n";
}
strout = strout +"\n";
return strout;
}
5.附m檔案:
1)addmatrix.m
function a = addmatrix(a1, a2)
%ADDMATRIX Add two matrices
% Copyright 2003 The MathWorks, Inc.
a = a1 + a2;
2) multiplymatrix.m
function m = multiplymatrix(a1, a2)
%MULTIPLYMATRIX Multiplies two matrices
% Copyright 2003 The MathWorks, Inc.
m = a1*a2;
3) eigmatrix.m
function e = eigmatrix(a1)
%EIGMATRIX Returns the eigen value of the given matrix
% Copyright 2003 The MathWorks, Inc.
e = eig(a1);
發布到目標機器上的時候需要拷貝過去的檔案有:MCRInstaller.exe,工程檔案的可執行程式,共用庫(DLL),共用庫對應的.ctf檔案。點擊運行MCRInstaller.exe檔案,安裝好MCR之後,將<mcr_root>\runtime\win32加入到系統的環境變數 path中去。