科學計算與視覺化之二(Matlab C/C++函式庫) (轉)

worldblog發表於2007-12-13
科學計算與視覺化之二(Matlab C/C++函式庫) (轉)[@more@]

1   引言

1984年美國的Mathworks公司推出Matlab,到目前為止,它已發展成為國際上最優秀的科技應用之一。其強大的科學計算與視覺化功能,簡單易用的開放式可擴充套件環境以及多達30多個面向不同領域而擴充套件的工具箱(Toolbox)支援,使得Matlab在許多學科領域中成為輔助設計與分析、演算法研究和應用開發的基本工具和首選平臺。但是由於其採用偽編譯的方式,在Matlab中編寫的無法脫離其工作環境而獨立執行。針對這個問題,Mathworks公司為Matlab提供了應用程式介面,允許Matlab和其它應用程式進行資料,並且提供了C/C++數學和圖形庫,為在其它語言Matlab高效演算法提供了可能。

C++語言是新一代的以面向()概念為根本的高階程式設計語言,它的物件導向的概念更加符合程式設計師開發軟體的思維習慣,類封裝性和模組化的構造非常適合軟體的移植和維護,使用C++開發有助於提高軟體工程的質量。VC++是美國公司利用C++的底層機理開發的新一代編譯器,與其它一些C++編譯器相同,都是以C++語言為編譯物件。VC++在編譯速度和程式碼方面,是同類產品的佼佼者,並且絕大多數的包都提供了對它的介面,這是VC++得到程式設計師認可的主要原因。對於理工科研究生和一些偏重於數值計算的工程技術人員,為了能夠較好的在短期之內完成一個兼具友善介面和穩定的計算核心的程式,利用軟體介面技術,可以藉助於第三方的函式庫。

2   Matlab應用程式介面

MATLAB提供的應用程式介面按目的一般來說可以分為以下三種:1.利用其它應用程式的優點,例如計算速度快和使用已有演算法而制定的介面;2.建立MATLAB與其它應用程式間的資料交換;3.拓廣MATLAB的應用範圍和應用手段。開發的相應應用程式為MEX、MAT檔案和MATLAB引擎應用程式。其中MEX檔案作為一種動態連結庫檔案,必須透過在MATLAB的工作環境內呼叫才能執行;MAT檔案用於資料交換,不能利用MATLAB提供的功能來完成計算任務;MATLAB引擎應用程式是一種可以獨立的應用程式,但在應用程式執行時,將在後臺啟動一個MATLAB程式,用於接收從應用程式傳送來的指令並執行,然後按照要求返回計算結果。綜上,基於MATLAB應用程式介面開發的應用程式並不完善,這種應用程式的執行不能脫離MATLAB環境。

3   VC++呼叫Matlab數學和圖形庫

6.1版本的Matlab軟體包中提供了C/C++的數學和圖形庫,透過其編譯器支援可以將Matlab中編寫的m檔案轉換成以C/C++程式碼的檔案,而且可以將m檔案生成dll庫,甚至我們可以直接呼叫其中的庫函式,生成併發布不必依賴Matlab的可執行檔案。透過mcc編譯器生成C/C++程式碼,進而可以在VC或者其它編譯器生成可獨立執行的應用程式,具體流程見下圖:

:namespace prefix = v ns = "urn:schemas--com:vml" />Office:office" />ectratio="t">

圖 1

下面具體討論如何利用Matlab編譯器從m檔案生成C/C++程式碼,並嵌入程式碼,生成執行時不需Matlab支援的應用程式。設matsum.m檔案,內容如下:

function sum = matbs( a, b )

% sum

sum = a + b

用mcc命令轉換為C/C++程式碼,命令列引數如下

生成C檔案

  mcc -t -L C matsum.m

生成C++檔案

  mcc -t -L Cpp matsum.m

生成動態連結庫函式

  mcc -t -W lib:sum -T link:lib matsum.m

注意①lib:後跟生成的庫檔名不能和原m檔名相同(此處為sum),②此處只能生成C語言方式的動態連結庫。該編譯命令共生成9個檔案,其中sum.lib和sum.dll是可以在C/C++應用程式中呼叫的動態連結庫檔案。

對生成的C++檔案進行分析,不難發現編譯器根據m檔案中的函式,生成一個對應的C++函式:static mwArray Mmatsum(int nargout_, mwArray a, mwArray b);並分別根據C++和Mex檔案的介面方式生成兩種形式的介面函式:extern mwArray matsum(mwArray a = mwArray::DIN, mwArray b = mwArray::DIN);和void mlxMatsum(int nlhs, mxArray * plhs[], int nrhs, mxArray * prhs[]);另外還有區域性函式表宣告/editor/Editor.htm#_ftn1" name=_ftnref1>1。

下面我們在VC++的環境下進行程式設計,為了論述方便首先生成一個基於C++的簡單控制檯應用程式,然後在專案中將用mcc命令生成的matsum.cpp和matsum.hpp包含到專案(project)中,如果該專案含有預編譯標頭檔案StdAfx.h,那麼在matsum.cpp所有包含檔案之首加入#include “StdAfx.h”。然後開啟Project/Setting…選單,在C/C++的Category中選Preprocessor,在預定義(Preprocessor definitions)欄加入MSVC,MSWIND,__STDC__,其中__STDC__可選,在C++專案中可省;選Code Generation,在執行時庫(Use run-time library)欄選擇Multithreaded DLL。在Link的/Library modules中新增庫檔案libmatlb.lib,libmx.lib,libmatpm.lib,當然對於使用圖形函式的程式必須使用相應的庫。

修改選項參考表一,一般在Code Generation中選擇Multithreaded DLL。

 

使用Static還是DLL工程

是否使用多執行緒庫?

是否使用C庫

 

使用的C連結庫存

 

Static

libc.lib

Static

libcd.lib

Static

libcmt.lib

Static

libcmtd.lib

DLL

msvcrt.lib(msvcrt.dll)

DLL

msvcrtd.lib(msvcrtd.dll)

DLL

msvcrt.lib(mvcrt.dll)

DLL

msvcrtd.lib(msvcrtd.dll)

表一

例程如下:

#include "stdafx.h"

// #include "matlab.hpp"  //C++方式

#include "matsum.hpp"

 

#pragma comment (lib, "libmatlb.lib")

#pragma comment (lib, "libmx.lib")

#pragma comment (lib, "libmatpm.lib")  // c++ maths library

 

int main(int argc, char* argv[])

{

  mwArray a(100),b(250);

  mwArray c;

  c=matsum(a,b);

 

  return 0;

}

我們可以用動態連結庫的方式呼叫m檔案中的函式,從前面看到的編譯命令,共生成包括sum.lib和sum.dll在內的9個檔案,複製lib和dll檔案到專案中。按以下格式呼叫:sumInitialize(); // 初始化mlfMatsum(); // 對應於Matsum ……  sumTenate(); // 釋放 注意:sum.h中的函式的引數和返回值大多為矩陣結構mxArry形式。因為是C語言方式,不詳細論述,例程如下:

{

  mxArray *ax, *bx, *cx;

sumInitialize();

// ax=mxCreateDoubleMatrix(1,1,mxREAL);

// bx=mxCreateDoubleMatrix(1,1,mxREAL);

mlfAssign(&ax,mlfScalar(200)); // C語言矩陣結構賦值

mlfAssign(&bx,mlfScalar(522));

cx=mlfMatsum(ax,bx);

// mlfPrintMatrix(cx);

sumTerminate();

}

4   VC++環境下的Matlab開發

從上面的轉換可以看出,利用Matlab編譯器命令生成的C/C++檔案,實際上其函式的輸入輸出引數為mwArray物件。那麼可以考慮直接在VC++或其它C++編譯器中利用Matlab的庫函式來完成簡單計算任務。

Matlab C/C++數學函式庫中最基本的資料型別為矩陣物件,即mwArray類物件,幾乎所有的庫函式均以它們作為計算和處理的物件,掌握mwArray物件的操作,對於學習Matlab C/C++數學庫的使用是至關重要的。

Matlab C/C++數學庫透過類mwArray對數值矩陣、稀疏矩陣、字元矩陣、單元矩陣和結構體矩陣提供了支援,矩陣物件的建立如下:

mwArray A; // 構造一個空矩陣物件

mwArray A(double/int);  // 數子的矩陣物件

mwArray A(int row, int col, double/int/unsigned short *real=NULL,

    double/int/unsigned short *image=NULL)

mwArray A(const mwArray&)  // 複製構造矩陣物件

C/C++呼叫Matlab函式將大量使用矩陣物件的操作,完成C/C++資料到mwArray物件的賦值和mwArray物件到C/C++資料的檢索。Matlab C/C++函式庫提供ExtractScalar和ExtractData兩個函式完成索引操作。另外用GetDate()和mxGetPr、mxGetPi組合可以得到指向mwArray物件的資料的指標。

在VC++環境中呼叫Matlab數學函式庫,還要注意異常的處理。Matlab定義一組以mwException為基類的異常類。異常處理如下:

try{

……

}

catch(mwException){

  mwDisplayException(ex);

……

}

5   提供簡單算例

 在計算機圖形學中關於曲線、曲面進行插值或擬合,將大量使用求解線性方程組。如在求B樣條曲線插值問題中,要先進行反求控制頂點,然後根據B樣條基求出進行插值,我們利用VC來完成介面,利用IMSL提供的數學函式完成計算。

例題:已知型值點序列Pi,i=0,1,2…,7:

 

 

P[0]

P[1]

P[2]

P[3]

P[4]

P[5]

P[6]

P[7]

Abscissae x

8.125

8.400

9.000

9.485

9.600

9.959

10.166

10.200

Ordinates y

0.0774

0.099

0.28

0.6

0.708

1.20

1.80

2.177

表二

求控制頂點序列。

反求B楊條曲線控制頂點的數學問題是:

 D表示de Boor控制頂點,P已知型值點列和邊界條件向量。

 

在VC中呼叫Matlab C/C++函式庫,利用矩陣的左除,可以的反求Deboor控制頂點的座標值,函式如下:

void resDeboorpt(int n, double *ppxs, point *pt, point *deboor)

{

  assert(pt!=deboor&&pt!=0&&deboor!=0);

  // assign point data

  double *ppt=new double[n*2];

  for(int i=0;i

  {

  *(ppt+i)=pt[i].x;

  *(ppt+i+n)=pt[i].y;

  }

  mwArray xzpt(n,2,ppt);

  // assign coefficient matrix

  mwArray xsjz(n,n,ppxs);

  mwArray kzdjz;

  try

  {

  // compute deboor point matrix

  kzdjz=mldivide(xsjz,6*xzpt);

  }

  catch(mwException ex)

  {

  mwDisplayException(ex);

  }

  delete []ppa; delete []ppt;

  for(i=0;i

  {

  deboor[i].x=kzdjz.ExtractScalar(i+1);

  deboor[i].y=kzdjz.ExtractScalar(i+n+1);

  }

}

 

計算結果 Di, i=0,1,…,9

 

D[0]=D[1]

D[2]

D[3]

D[4]

D[5]

D[6]

P[7]

D[8]=D[9]

Abscissae x

8.08523

8.32384

9.01941

9.59854

9.49644

10.0157

10.1948

10.201

Ordinates y

0.07852

0.07183

0.22819

0.69544

0.59008

1.19226

1.84088

2.24422

表三

Matlab C/C++函式庫中的宣告方式是extern的,在外部引用庫函式時無需另外宣告。由於Matlab C/C++庫函式採用動態連結庫的方式,所以在釋出自己的應用程式時必須包括相應的應用程式擴充套件檔案。具體方法如下:執行%MATLAB% externlibmglinstaller.exe,所生成的*.dll 包括bin and toolbox打包即可。注意在執行機上設定路徑。

6   小結

本文針對Matlab應用程式介面,詳細論述了在視覺化環境中,利用VC++呼叫Matlab數學圖形函式庫,編制可以獨立執行的應用程式。經過實踐證明,可以在很大程度上提高軟體開發,增加演算法的穩定程度。目前已有一些利用混合程式設計開發的軟體:如雷達特性分析、實時預測軟體等,在實際中已得到了應用。

參考文獻3.


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992682/,如需轉載,請註明出處,否則將追究法律責任。

相關文章