VC中調用matlab函數

來源:互聯網
上載者:User
 

感覺這篇比上一篇講得更清楚,尤其是有關API介面的函數

Visual C++是當前主流的應用程式開發環境之一,開發環境強大,開發的程式執行速度快。但在科學計算方面函數庫顯得不夠豐富、讀取、顯示資料圖形不方便。Matlab是一款將數值分析、矩陣計算、訊號處理和圖形顯示結合在一起,包含大量高度整合的函數可供調用,適合科學研究、工程設計等眾多學科領域使用的一種簡潔、高效的編程工具。不過由於Matlab使用的是解釋性語言,大大限制了它的執行速度和應用場合。基於VC和Matlab混合編程是很多熟悉VC++編程而又需要進行科學計算、資料模擬的科研人員常用的一種方式,其中最簡單也最直接的方法就是調用Matlab引擎。本文以下部分將詳細介紹通過VC++6.0調用Matlab6.5引擎來達到VC++與Matlab資料共用編程的方法。

  1. 什麼是Matlab引擎

  所謂Matlab引擎(engine),是指一組Matlab提供的介面函數,支援C/C++、Fortran等語言,通過這些介面函數,使用者可以在其它編程環境中實現對Matlab的控制。可以主要功能有:

  ★ 開啟/關閉一個Matlab對話;

  ★ 向Matlab環境發送命令字串;

  ★ 從Matlab環境中讀取資料;

  ★ 向Matlab環境中寫入資料。

  與其它各種介面相比,引擎所提供的Matlab功能支援是最全面的。通過引擎方式,應用程式會開啟一個新的Matlab進程,可以控制它完成任何計算和繪圖操作。對所有的資料結構提供100%的支援。同時,引擎方式開啟的Matlab進程會在工作列顯示自己的表徵圖,開啟該視窗,可以觀察主程式通過engine方式控制Matlab啟動並執行流程,並可在其中輸入任何Matlab命令。

  實際上,通過引擎方式建立的對話,是將Matlab以ActiveX控制項方式啟動的。在Matlab初次安裝時,會自動執行一次:

matlab /regserver

  將自己在系統的控制項陳列庫中註冊。如果因為特殊原因,無法開啟Matlab引擎,可以在Dos命令提示字元後執行上述命令,重新註冊。

  2. 配置編譯器

  要在VC中成功編譯Matlab引擎程式,必須包含引擎標頭檔engine.h並引入Matlab對應的庫檔案libmx.lib、libmat.lib、libeng.lib。具體的說,開啟一個工程後,做如下設定(以VC6為例):

  1) 通過菜單工程/選項,開啟設定屬性頁面,進入Directories頁面,在目錄下拉式清單方塊中選擇Include files,添加路徑:"C:/matlab/extern/include"(假定matlab安裝在C:/matlab目錄)。

  2) 選擇Library files,添加路徑:C:/matlab/extern/lib/win32/microsoft/msvc60。

  3) 通過菜單工程/設定,開啟工程設定屬性頁面,進入Link頁面,在Object/library modules編輯框中,添加檔案名稱libmx.lib libmat.lib libeng.lib。

  以上步驟1)、2)只需設定一次,而步驟3)對每個工程都要單獨設定,對於其它C++編譯器如Borland C++ Builder,設定大體相同,不再贅述。

  3. 引擎API詳解

  在調用Matlab引擎之前,首先應在相關檔案中加入一行:#include "enging.h",該檔案包含了引擎API函數的說明和所需資料結構的定義。可以在VC中調用的引擎函數分別如下:

  3.1 引擎的開啟和關閉

  engOpen-開啟Matlab engine

  函式宣告:

Engine *engOpen(const char *startcmd);

  參數startcmd是用來啟動Matlab引擎的字串參數,在Windows作業系統中只能為NULL。

  函數傳回值是一個Engine類型的指標,它是在engine.h中定義的engine資料結構。

  EngClose-關閉Matlab 引擎

  函式宣告:

int engClose(Engine *ep);

  參數ep代表要被關閉的引擎指標。

  函數傳回值為0表示關閉成功,返回1表示發生錯誤。

  例如,通常用來開啟/關閉Matlab引擎的代碼如下:

Engine *ep; //定義Matlab引擎指標。
if (!(ep=engOpen(NULL))) //測試是否啟動Matlab引擎成功。
{
MessageBox("Can't start Matlab engine!" );
exit(1);
}
. …………
engClose(ep); //關閉Matlab引擎。

  3.2 向Matlab發送命令字串

  engEvalString-發送命令讓Matlab執行。

  函式宣告:

int engEvalString(Engine *ep, Const char *string);

  參數ep為函數engOpen返回的引擎指標,字串string為要matlab執行的命令。

  函數傳回值為0表示成功執行,返回1說明執行失敗(如命令不能被Matlab正確解釋或Matlab引擎已經關閉了)。

  3.3 擷取Matlab命令視窗的輸出

  要在VC中獲得函數engEvalString發送的命令字串被Matlab執行後在matlab視窗中的輸出,可以調用engOUtputBuffer函數。

  函式宣告:

int engOutputBuffer(Engine *ep, char *p, int n);

  參數ep為Matlab引擎指標,p為用來儲存輸出結構的緩衝區,n為最大儲存的字元個數,通常就是緩衝區p的大小。該函數執行後,接下來的engEvalString函數所引起的命令列輸出結果會在緩衝區p中儲存。如果要停止儲存,只需調用代碼:engOutputBuffer(ep, NULL, 0)。

  3.4 讀寫Matlab資料

  3.4.1從Matlab引擎工作空間中擷取變數。

mxArray *engGetVariable(Engine *ep, const char *name);

  參數ep為開啟的Matlab引擎指標,name為以字串形式指定的數組名。

  函數傳回值是指向name數組的指標,類型為mxArray*(mxArray資料類型在本文第4節詳細簡介)。

  3.4.2 向Matlab引擎工作空間寫入變數。

int engPutVariable(Engine *ep, const char *name, const mxArray *mp);

  參數ep為開啟的Matlab引擎指標,mp為指向被寫入變數的指標,name為變數寫入後在Matlab引擎工作空間中的變數名。
函數傳回值為0表示寫入變數成功,傳回值為1表示發生錯誤。

  3.5 調用引擎時顯示/隱藏Matlab主視窗

  預設情況下,以engine方式調用Matlab的時候,會開啟Matlab主視窗,可在其中隨意操作。但有時也會干擾應用程式的運行,可用以下設定是否顯示該視窗。

int engSetVisible(Engine *ep, bool value);

  參數ep為開啟的Matlab引擎指標,value為是否顯示的標誌,取值true(或1)表示顯示Matlab視窗,取值false(或0)表示隱藏Matlab視窗。

  函數傳回值為0表示設定成功,為1表示有錯誤發生。

  要獲得當前Matlab視窗的顯示/隱藏情況,可以調用函數:

int engGetVisible(Engine *ep, bool *value);

  參數ep為開啟的Matlab引擎指標,Value為用來儲存顯示/隱藏情況的變數(採用指標方式傳遞)。

  函數傳回值為0表示擷取成功,為1表示有錯誤發生。
4. 資料類型mxArray的操作

  在上節的Matlab引擎函數中,所有與變數有關的資料類型都是mxArray類型。資料結構mxArray以及大量的mx開頭的函數,廣泛用於Matlab 引擎程式和Matlab C數學庫中。mxArray是一種很複雜的資料結構,與Matlab中的array相對應,我們只需熟悉Matlab的array類型和幾個常用的mxArray函數即可。

  在VC中,所有和Matlab的資料互動都是通過mxArray來實現的,在使用mxArray類型的程式中,應包含標頭檔matrix.h,不過在引擎程式中,一般會包含標頭檔engine.h,該檔案裡面已經包含了matrix.h,因此無需重複包含。

  4.1 建立和清除mxArray型資料

  Matlab有很多種變數類型,對應於每種類型,基本上都有一個函數用於建立,但它們都有相同的資料結構,就是mxArray。

  數組的建立採用mxCreatexxx形式的函數,例如建立一個double類型數組,可用函數mxCreateDoubleMatrix,函數形式如下:

mxArray *mxCreateDoubleMatrix(int m, int n, mxComplexity ComplexFlag);

  參數m和n為矩陣的函數和列數。ComplexFlag為常數,用來區分矩陣中元素是實數還是複數,取值分別為mxREAL和mxCOMPLEX。

  例如,建立一個3行5列的二維實數數組,可用如下語句:

mxArray *T = mxCreateDoubleMatrix(3, 5, mxREAL);

  對應的,要刪除一個數組mxDestroyArray,該函式宣告如下:

void mxDestroyArray(mxArray *array_ptr);

  參數array_ptr為要刪除的數組指標。

  例如,要刪除上面建立的數組T,可用如下語句:

mxDestroyArray(T);

  類似的建立函數還有:

mxArray *mxCreateString(const char *str);

  建立一個字串類型並初始化為str字串。

  一般的在VC與Matlab互動中,以上兩種類型就夠了,其它類型數組的建立這裡不再介紹。

  4.2 管理mxArray資料類型

  4.2.1 管理mxArray資料大小

  要獲得mxArray數組每一維上元素的個數,可以用mxGetM和mxGetN函數。其中mxGetM用來獲得數組第一維的元素個數,對於矩陣來說就是行數。

int mxGetM(const mxArray *array_ptr); //返回array_ptr對應數組第一維的元素個數(行數)
int mxGetN(const mxArray *array_ptr); //返回array_ptr對應數組其它維的元素個數,對於矩陣來說是列數。對於多維陣列來說是從第2維到最後一維的各維元素個數的乘積。

  要獲得某一特定維的元素個數,則要用函數:

const int *mxGetDimensions(const mxArray *array_ptr);

  該函數返回array_ptr各維的元素個數儲存在一個int數組中返回。對於常用的矩陣來說,用mxGetM和mxGetN兩個函數就可以了。

  另外還可以通過mxGetNumberOfDimensions來獲得數組的總的維數,用mxSetM、mxSetN設定矩陣的行數和列數,函數說明如下:

mxGetNumberOfDimensions(const mxArray *array_ptr); //返回數組的維數
void mxSetM(mxArray *array_ptr, int m); //設定數組為m行
void mxSetN(mxArray *array_ptr, int n); //設定數組為n列

  4.2.2 判斷mxArray數群組類型

  在對mxArray類型的變數進行操作之前,可以驗證以下其中的數組的資料類型,比如是否為double數組、整數、字串、邏輯值等,以及是否為某種結構、類、或者是特殊類型,比如是否為空白數組,是否為inf、NaN等。常見的判斷函數有:

bool mxIsDouble(const mxArray *array_ptr);
bool mxIsComplex(const mxArray *array_ptr);
bool mxIsChar(const mxArray *array_ptr);
bool mxIsEmpty(const mxArray *array_ptr);
bool mxIsInf(double value);
…… ……

  這些函數比較簡單,意義自明,不再解釋。

  4.2.3 管理mxArray數組的資料

  對於常用的double類型的數組,可以用mxGetPr和mxGetPi兩個函數分別獲得其實部和虛部的資料指標,這兩個函數的聲明如下:

double *mxGetPr(const mxArray *array_ptr); //返回數組array_ptr的實部指標
double *mxGetPi(const mxArray *array_ptr); //返回數組array_ptr的虛部指標

  這樣,就可以通過獲得的指標對mxArray類型的數組中的資料進行讀寫操作。例如可以用函數engGetVariable從Matlab工作空間讀入mxArray類型的數組,然後用mxGetPr和mxGetPi獲得資料指標,對並其中的資料進行處理,最後調用engPutVariable函數將修改後的數組重新寫入到Matlab工作空間。具體實現見第5節程式執行個體。

5. 程式執行個體

  對大部分軟體研發人員來說利用VC編程方便、高效,但是要顯示資料圖形就不那麼容易了,這時候不防藉助Matlab引擎輔助畫圖做資料分析。下面通過執行個體示範如何利用VC調用Matlab繪圖,程式的主要功能是在VC中對數組x計算函數值y=sin(x) ±log(x),然後調用Matlab繪製y對x的圖形。

  在VC中建立工程,編寫代碼如下:

#include <iostream>
#include <math.h>
#include "engine.h"
using namespace std;
void main()
{
 const int N = 50;
 double x[N],y[N];
 int j = 1;
 for (int i=0; i<N; i++) //計算數組x和y
 {
  x[i] = (i+1);
  y[i] = sin(x[i]) + j * log(x[i]); //產生-之間的隨機數賦給xx[i];
  j *= -1;
 }
 Engine *ep; //定義Matlab引擎指標。
 if (!(ep=engOpen(NULL))) //測試是否啟動Matlab引擎成功。
 {
  cout <<"Can't start Matlab engine!" <<endl;
  exit(1);
 }

 //定義mxArray,為行,N列的實數數組。
 mxArray *xx = mxCreateDoubleMatrix(1,N, mxREAL);
 mxArray *yy = mxCreateDoubleMatrix(1,N, mxREAL); //同上。

 memcpy(mxGetPr(xx), x, N*sizeof(double)); //將數組x複製到mxarray數組xx中。
 memcpy(mxGetPr(yy), y, N*sizeof(double)); //將數組x複製到mxarray數組yy中。

 engPutVariable(ep, "xx",xx); //將mxArray數組xx寫入到Matlab工作空間,命名為xx。
 engPutVariable(ep, "yy",yy); //將mxArray數組yy寫入到Matlab工作空間,命名為yy。

 //向Matlab引擎發送畫圖命令。plot為Matlab的畫圖函數,參見Matlab相關文檔。
 engEvalString(ep, "plot(xx, yy); ");

 mxDestroyArray(xx); //銷毀mxArray數組xx和yy。
 mxDestroyArray(yy);

 cout <<"Press any key to exit!" <<endl;
 cin.get();
 engClose(ep); //關閉Matlab引擎。
}

6. 小結

  本文詳細的介紹了Matlab引擎使用方法並示範了一個簡單的利用VC調用Matlab畫圖的程式執行個體。大多數時候,程式員可以利用Matlab強大的資料讀寫、顯示能力和VC編程的高效率。例如,在Matlab中要讀入一幅任意格式的映像均只需一條命令i=imread('test.jp');映像資料矩陣便存放在了二維數組i中,可以通過VC讀入該數組進行相關處理再調用Matlab顯示,這種混合編程方式能大大提高工作效率。

  當然,利用VC編譯的Matlab引擎程式,運行環境中還必須Matlab的支援,如果要編譯完全脫離Matlab的程式,可採用其它方式,如利用第三方Matcom程式編譯獨立的可執行程式等

 

From:http://hi.baidu.com/kenter83/blog/item/153275d9b1ef88ef3b012f60.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.