14-3 穻@伂{w

使用MATLAB編譯器,我們也可以產生共享程式庫(Shared Libraries),包含所有由使用者定義的函式,以便讓其他獨立應用程式來呼叫。

例如,假設我們要產生一個共享程式庫,其功能包含矩陣相乘和反矩陣的計算,此時我們可先定義這兩個 MATLAB 函式,myMatInv.m(計算反矩陣)及 myMatMultiply.m(計算矩陣相乘):

Example 1: 14-matlab編譯器/myMatInv.mfunction invMat = myMatInv(mat) %myMatInv: Generate the inverse matrix of the given matrix % Roger Jang, 20080211 invMat=inv(mat);

Example 2: 14-matlab編譯器/myMatMultiply.mfunction out = myMatMultiply(mat1, mat2) %myMatEig: Generate the product of two given matrices % Roger Jang, 20080211 out=mat1*mat2;

接著我們要將這兩個 MATLAB 函式編譯成共享程式庫,程式庫名稱為 matLib,所使用的指令如下:

mcc -B csharedlib:myMatLib myMatInv.m myMatMultiply.m -d sharedLibrary

此時會在輸出目錄 sharedLibrary 產生數個檔案,主檔名都是 myMatLib,這些檔案即是 myMatLib 程式庫,我們可以使用一般獨立應用程式來呼叫這個程式庫內所定義的函式。由於這個程式庫是由兩個 MATLAB 函式編譯所得,因此我們可以得到兩個對應的 C 函式,分別是 mlfMyMatInv 及 mlfMyMatMultiply,對應關係如下:

使用共享程式庫 myMatLib.dll 來呼叫這兩個 C 函式的獨立應用程式範例如下:

原始檔(14-matlab編譯器/myMatLibMain.c):(灰色區域按兩下即可拷貝)
/*=======================================================
 * 此範例程式可以呼叫 MATLAB 編譯器所產生的程式庫 myMatLib
 * Roger Jang, 20080211, 20120812
 *=======================================================*/

#include <stdio.h>
/* 導入 MCR 標頭檔以及(由 MATLAB 編譯器產生)特定應用相關的標頭檔 */
#include "myMatLib.h"	


/* 顯示C資料型態為 mxArray 的雙倍精準陣列 */
void matDisplay(const mxArray* in){
	int i, j;
	int rowNum = mxGetM(in);	/* 橫列個數 */
	int colNum = mxGetN(in);	/* 直行個數 */
	double *data = mxGetPr(in);	/* 指到輸入陣列中的雙倍精準資料 */
    
	/* 印出資料 */
	for(i=0; i<colNum; i++){
		for(j=0; j<rowNum; j++)
			printf("%4.2f\t", data[j*colNum+i]);
		printf("\n");
	}
	printf("\n");
}

/* 主要工作函式 */
void *mainFunction(int *errorCode){
	mxArray *in1, *in2;	/* 定義送到程式庫函式的輸入矩陣 */
	mxArray *out = NULL;	/* 定義程式庫函式的輸出矩陣 */
	double data[] = {1, 3, 5, 2, 4, 6, 0, 8, 9};	/* 測試用的資料 */

	/* 呼叫 mclInitializeApplication() 以確認此應用程式已經被正確地啟始 */
	if(!mclInitializeApplication(NULL, 0)){
		fprintf(stderr, "錯誤:無法啟始應用程式!\n");
		*errorCode=-1;
		return;
	}
	/* 呼叫 myMatLibInitialize() 以確認 MATLAB編譯器的程式庫已經被正確地啟始 */
	if (!myMatLibInitialize()){
		fprintf(stderr,"錯誤:無法啟始程式庫!\n");
		*errorCode=-2;
		return;
	}
    
	/* 創造輸入矩陣 */
	in1 = mxCreateDoubleMatrix(3, 3, mxREAL);
	in2 = mxCreateDoubleMatrix(3, 3, mxREAL);
	memcpy(mxGetPr(in1), data, 9*sizeof(double));	/* 將 data 中的資料拷貝至 in1 */
	memcpy(mxGetPr(in2), data, 9*sizeof(double));	/* 將 data 中的資料拷貝至 in2 */
    
        /* 呼叫由 MATLAB 編譯器產生的程式庫 myMatLib */
	/* 計算矩陣相乘 */
	mlfMyMatMultiply(1, &out, in1, in2);
	printf("矩陣相乘的結果:\n"); matDisplay(out);
	mxDestroyArray(out); out=NULL;	/* 收回配置給 out 的記憶體 */
	/* 計算反矩陣 */
	mlfMyMatInv(1, &out, in1);
	printf("計算反矩陣的結果:\n"); matDisplay(out);
	mxDestroyArray(out); out=NULL;	/* 收回配置給 out 的記憶體 */

	/* 收回配置給 in1 和 in2 的記憶體 */
	mxDestroyArray(in1); in1=NULL;
	mxDestroyArray(in2); in2=NULL;

	/* 呼叫 myMatLibTerminate() 以終止應用程式庫 */
	myMatLibTerminate();
	/* 呼叫 mclTerminateApplication() 以終止此應用程式 */
	mclTerminateApplication();
}

/* 主程式 */
int main(){
	int errorCode=0;
	mainFunction(&errorCode);
	return(errorCode);
}

若要編譯此獨立程式,可在 MATLAB 命令視窗輸入如下:

mbuild -IsharedLibrary myMatLibMain.c sharedLibrary/myMatLib.lib

其中 -IsharedLibrary 負責告知 mbuild 到 sharedLibrary 去搜尋標頭檔 myMatLib.h,而 sharedLibrary/myMatLib.lib 則是負責載明 sharedLibrary/myMatLib.dll 的使用方式。執行完上述指令後,即可產生獨立應用程式 myMatLibMain.exe,但在使用此可執行檔之前,我們必須讓作業系統知道 myMatLib.dll 的位置,否則 myMatLabMain.exe 無法使用此共享程式庫,有兩種方式可以達到此目的:

  1. 將 sharedLibrary/myMatLib.dll 拷貝到與 myMatLibMain.exe 同一層目錄(假設是目前目錄),對應的 DOS 指令是: copy /y sharedLibrary/myMatLib.dll .
  2. 將 sharedLibrary 加到 DOS 的搜尋路徑之中。 set path=%path%;sharedLibrary
完成上述設定後,只要在 DOS 命令視窗下輸入「myMatLibMain」,即可看到此程式碼執行的結果。

若我們將上述步驟整合在一個指令檔,可以得到下列範例:

Example 4: 14-matlab編譯器/mbuild01.mfprintf('MATLAB version=%s\n', version); if ~exist('sharedLibrary'), mkdir('sharedLibrary'); end fprintf('Creating shared library myMatLib and put it under sharedLibrary...\n'); tic; mcc -B csharedlib:myMatLib myMatInv.m myMatMultiply.m -d sharedLibrary; fprintf('Time for creating shared library = %g sec\n', toc); fprintf('Compiling myMatLibMain.c...\n'); mbuild -IsharedLibrary myMatLibMain.c sharedLibrary/myMatLib.lib fprintf('Copying myMatLib.dll to the current directory...\n'); copyfile('sharedLibrary/myMatLib.dll', '.'); fprintf('Running DOS command: myMatLibMain.exe...\n'); !myMatLibMain.exe MATLAB version=7.14.0.739 (R2012a) Creating shared library myMatLib and put it under sharedLibrary... DEMO Compiler license. The generated application will expire 30 days from today, on Sat Sep 15 20:07:18 2012. Time for creating shared library = 50.5487 sec Compiling myMatLibMain.c... Copying myMatLib.dll to the current directory... Running DOS command: myMatLibMain.exe... 矩陣相乘的結果: 7.00 10.00 16.00 55.00 70.00 104.00 68.00 88.00 129.00 計算反矩陣的結果: -0.86 -1.29 1.14 0.93 0.64 -0.57 -0.14 0.29 -0.14

有關 mcc 及 mbuild 指令的選項很多,讀者可由「doc mcc」及「doc mbuild」得到完整的線上支援,在此不再贅述。


MATLAB程式設計:進階篇