Matlab調用C程式

來源:互聯網
上載者:User

標籤:mex檔案   dll   matlab   

Matlab是矩陣語言,如果運算可以用矩陣實現,其運算速度非常快。但若運算中涉及到大量迴圈,Matlab的速度令人難以忍受的。當必須使用for迴圈且找不到對應的矩陣運算來等效時,可以將耗時間長度的函數用C語言實現,並編譯成Mex檔案,Matlab便可以像調用內建函數一樣調用C編寫的函數。Mex檔案其實是一種動態連結程式庫,舊版本Matlab可以直接調用.dll,新版本要調用.mexw32或.mexw64檔案。

編譯過程需要C語言編譯器,在Matlab中鍵入mex –setup進行安裝與配置。

MEX檔案的原始碼組成

(1)功能子程式。該過程包含了Mex檔案實現計算功能的代碼,是標準的C語言子程式。

(2)入口子程式。該過程提供功能子程式與Matlab之間的介面,以mexFunction函數實現。注意,入口過程的名稱必須是mexFunction,並且包含四個參數,即

void mexFunction(int nlhs,mxArray*plhs[],int nrhs,const mxArray *prhs[]);

nrhs(left hand side): 輸入參數的個數;

prhs是一個輸入數組,其內容為指標,指向mxArray類型的資料(MATLAB中所有資料都是以矩陣的形式mxArray儲存的)。

nlhs, plhs含義類似。

具體地,若在Matlab中執行[a,b]=test(c,d,e) ,則nlhs=2, nrhs=3,prhs[0]指向c,prhs[1]指向d,prhs[2]指向e(可以理解為:prhs[0]=&c, prhs[1]=&d, prhs[2]=&e),注意prhs是const指標數組,故不能改變其指向內容;函數返回時將plhs[0],plhs[1]指向的內容賦給a,b(可以理解為a=*plhs[0], b=*plhs[1])。

:建立add.c,源碼如下:

#include "mex.h"  double add(double x, double y){    return x + y;} void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[]){    double *a;    double b, c;    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);    a = mxGetPr(plhs[0]);    b = *(mxGetPr(prhs[0]));    c = *(mxGetPr(prhs[1]));    *a = add(b, c);}

將add.c拷貝至Matlab目前的目錄,執行mex add.c,產生add.mexw64,該檔案實現求和功能。此時便可在Matlab中調用該函數:

>> output = add(1.1, 2.2); 

分析:

#include "mex.h"

Mex源檔案必須包含mex.h,該標頭檔提供了大量Matlab與C(或Fortran)語言的之間的介面函數,函數首碼有mex-和mx-兩種,帶mx-首碼的大多是對mxArray資料進行操作的函數,如mxIsDouble,mxCreateDoubleMatrix等;而帶mex-首碼的則大多是與Matlab環境進行互動的函數,如mexPrintf,mexErrMsgTxt等。具體可參考Apiref.pdf。

plhs[0] = mxCreateDoubleMatrix(1, 1,mxREAL);

建立一個1x1的double類型的矩陣,返回剛建立的mxArray的地址,賦給指標plhs[0];

a = mxGetPr(plhs[0]);

返回指標plhs[0]所指向矩陣的第一個實數的地址,並賦給a;

b = *(mxGetPr(prhs[0]));

擷取指標prhs[0]指向矩陣的第一個實數,並賦給b;

*a = add(b, c);

調用C程式add,計算b,c之和並賦給a指向的內容;

例:建立myhilb.c,源碼如下:

#include "mex.h"void myhilb(double *y,int n){    int i,j;    for(i=0;i<n;i++)        for(j=0;j<n;j++)            *(y+j+i*n)=1/((double)i+(double)j+1);}void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]){    double x,*y;       if (nrhs!=1)        mexErrMsgTxt("One inputs required.");    if (!mxIsDouble(prhs[0])||mxGetN(prhs[0])*mxGetM(prhs[0])!=1)        mexErrMsgTxt("Input must be scalars.");    x=mxGetScalar(prhs[0]);    plhs[0]=mxCreateDoubleMatrix(x,x,mxREAL);    y=mxGetPr(plhs[0]);    myhilb(y,(int)x);}

將myhilb.c拷貝至Matlab目前的目錄,執行mex myhilb.c,產生myhilb.mexw64,該檔案實現了計算Hilbert矩陣的功能(Hilbert矩陣:H(i,j)=1/(i+j-1))。

此時便可在Matlab中調用該函數:

>> output = myhilb (6);

分析:

mexFunction中進行了參數檢查,函數mexErrMsgTxt顯示出錯資訊後即退回到MATLAB。

mxGetScalar:擷取輸入矩陣第一個元素的實數部分;mxGetM:擷取矩陣的行數。

為了測試一下Mex檔案與m檔案的速度差異,編寫m檔案並運行之:

ticm=10000;a=zeros(m,m);for i=1:m     for j=1:m         a(i,j)=1/(i+j);     endendtoc

結果:Elapsed time is3.620924 seconds.

接著運行Mex檔案

ticoutput = myhl(10000);toc

結果:Elapsed timeis 0.730596 seconds.

可以看出Mex檔案與M檔案速度差異很大。

VS2010產生Mex檔案(本人64位作業系統)

上述利用Matlab編譯產生Mex檔案,同樣也可以使用VS2010產生Mex檔案,只不過需要對VS環境進行配置,過程如下:

1、  建立一個win32 控制台的dll 空項目”myhilb”;

2、  建立源檔案myhilb.c,將上述myhilb.c內容拷進即可;

3、  添加.def檔案,內容為:

LIBRARY

EXPORTSmexFunction

4、  設定項目屬性, 開啟項目屬性配置頁:

(1)C/C++—>常規—>附加元件封裝含目錄,輸入matlab下安裝目錄下\extern\include

本人輸入E:\Matlab2010\Install\extern\include

(2)連結器->常規—>附加庫目錄,輸入matlab下安裝目錄下\extern\lib\win64\microsoft

本人輸入E:\Matlab2010\Install\extern\lib\win64\microsoft

(3)連接器 ->輸入->附加依賴項,輸入

libmx.lib

libeng.lib

libmat.lib

libmex.lib

(4)連結器->常規—>輸出檔案,輸入$(OutDir)$(TargetName).mexw64(若此處不更改,可在產生dll檔案後將尾碼名改為mexw64即可,這也驗證了Mex實際上就是DLL,只是尾碼名不同罷了)

(5)連結器->進階—>目標電腦,設為MachineX64(32位系統不用更改)

設定好點擊應用,執行了(5)的64位系統還需要在執行:

產生—>組態管理員—>活動解決平台,改為x64

5、按F7編譯工程,會在Debug下產生.mexw64檔案,如:


VS中單步調試Mex檔案

在Matlab環境下使用 mex  –g myhilb.c命令進行調試,但無法加斷點進行單步調試,故需轉到VS環境下調試。

不管是利用VS還是利用Matlab產生Mex檔案,只要有c源檔案和Mex檔案就可以利用VS對Mex來源程式加斷點進行單步調試(我們用上面myhilb.c和myhilb.mexw64做測試)。

1、將Matlab目前的目錄改為Mex檔案(C檔案)所在目錄;

2、在VS2010中開啟C檔案,調試—>附加到進程,附加MATLAB.exe;

3、VS中在C源碼中添加斷點,在Matlab命令視窗調用Mex檔案提供的介面;

如Matlab執行:out=myhilb(6);



此時,VS2010中便可按F10進行單步調試:


要說明的是,在調試階段Matlab處於假死狀態,另外,Matlab調用了Mex檔案後需要執行clear all命令後才能刪除Mex檔案;

同樣地,若利用VS產生Mex檔案後直接將Matlab目前的目錄改至Debug目錄進行調試,則調試完必須執行clear all指令才能重新編譯工程。

參考:

http://blog.sina.com.cn/s/blog_468651400100coas.html

http://www.cppblog.com/xiaozhixd/articles/108490.html

http://www.linuxidc.com/Linux/2012-08/68148.htm

http://blog.sina.com.cn/s/blog_a7e72e940101cti9.html

http://blog.csdn.net/raodotcong/article/details/6317273


Matlab調用C程式

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.