Linux 下C與matlab 混編,linuxmatlab混編
1 概述1.1 Matlab簡介
MATLAB是美國MathWorks公司出品的商業數學軟體,用於演算法開發、資料視覺效果、資料分析以及數值計算的進階技術計算語言和互動式環境,主要包括MATLAB和Simulink兩大部分。MATLAB應用非常之廣泛!
MATLAB 亦可以與其他進階語言C/ C++/ C#/Java/Fortran等進行混合編程。
1.2 什麼是Matlab引擎
所謂Matlab引擎(engine),是指一組Matlab提供的介面函數,支援C/C++、Fortran等語言,通過這些介面函數,使用者可以在其它編程環境中實現對Matlab的控制。
2 啟動Matlab前相關環境設定2.1 matlab引擎依賴條件
matlab引擎依賴/bin/csh啟動,所以不管你使用何種shell,都必須安裝csh
#yum install chs (centos/redhat平台)
#apt-get install chs (ubuntu平台)
2.2 matlab引擎依賴的動態庫檔案目錄必須在系統當前的庫函數搜尋路徑中
即可以設定環境
LD_LIBRARY_PATH= /usr/local/matlab/bin/glnx86 (ps:32環境下)
LD_LIBRARY_PATH=/usr/local/matlab/bin/glnxa64 (ps:64 環境下)
2.3 用gcc或者g++ 編譯
編寫好的程式編譯時間需要指定標頭檔目錄,連結時需要指定庫檔案目錄,並且需要指定所需要的庫檔案
相關命令如下:
#gcc -I/usr/local/matlab/extern/include -o matlab.o matlab.c
#gcc -L/usr/local/matlab/bin/glnx86 -Wl,-rpath,/usr/local/matlab/bin/glnx86 -o matlab matlab.o -leng -lmx
2.4 相關環境設定總結:
上述2.1 2.2 2.3對如何編譯C與matlab 進行了說明,但是步驟較多,程式編譯較為繁瑣。因為我們可以通過一次環境變數的設定來達到這種目的。
export PATH=$PATH:"/usr/local/matlab/bin"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"/usr/local/matlab/bin/glnxa64"
export C_INCLUDE_PATH=$C_INCLUDE_PATH:"/usr/local/matlab/extern/include"
export LIBRARY_PATH=$LIBRARY_PATH:"/usr/local/matlab/bin/glnxa64"
把上述環境變數的設定寫進檔案名稱為xx.env的檔案中,然後使用命令source執行
#source xx.env
執行完上述命令後就把所有的環境變數設定完畢。
接下來就可以用gcc/g++ 進行編譯:
#gcc test.c -o test -leng -lmex -lmx
註:/usr/local/matlab/ 此路徑為Matlab安裝時的路徑,可根據實際情況進行變動。
3 Matlab與C的介面函數介紹3.1 Matlab引擎的啟動與關閉
engOpen-開啟Matlab engine
函式宣告:
Engine *engOpen(const char *startcmd);
參數startcmd是用來啟動Matlab引擎的字串參數為NULL。
函數返回值是一個Engine類型的指標,它是在engine.h中定義的engine資料結構。
EngClose-關閉Matlab 引擎
函式宣告:
int engClose(Engine *ep);
參數ep代表要被關閉的引擎指標。
函數返回值為0表示關閉成功,返回1表示發生錯誤。
例如:通常用來開啟/關閉Matlab引擎的代碼如下:
Engine *ep; //定義Matlab引擎指標。 if (!(ep=engOpen(NULL))) //測試是否啟動Matlab引擎成功。 { perror("Can't start Matlab engine!" ); exit(1); } ………… engClose(ep); //關閉Matlab引擎。
|
3.2 建立和清除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為要刪除的數組指標。 |
類似的建立函數還有:
函式宣告:
mxArray *mxCreateString(const char *str);
建立一個字串類型並初始化為str字串。
一般的在C與Matlab互動中,以上兩種類型就夠了,其它類型數組的建立這裡不再介紹。
3.3 管理mxArray的資料類型3.3.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設定矩陣的行數和列數,函數說明如下:
int mxGetNumberOfDimensions(const mxArray *array_ptr); //返回數組的維數
void mxSetM(mxArray *array_ptr, int m); //設定數組為m行
void mxSetN(mxArray *array_ptr, int n); //設定數組為n列
3.3.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);
…… ……
這些函數比較簡單,不再解釋。
3.3.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工作空間。
3.4 調用引擎時顯示/隱藏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表示有錯誤發生。
3.5 讀寫Matlab資料3.5.1 從Matlab引擎工作空間中擷取變數
函式宣告:
mxArray *engGetVariable(Engine *ep, const char *name);
參數ep為開啟的Matlab引擎指標,name為以字串形式指定的數組名。
函數返回值是指向name數組的指標
3.5.2 向Matlab引擎工作空間寫入變數
函式宣告:
int engPutVariable(Engine *ep, const char *name, const mxArray *mp);
參數ep為開啟的Matlab引擎指標,mp為指向被寫入變數的指標,name為變數寫入後在Matlab引擎工作空間中的變數名。
函數返回值為0表示寫入變數成功,返回值為1表示發生錯誤。
3.6 向Matlab發送命令字串
engEvalString-發送命令讓Matlab執行。
函式宣告:
int engEvalString(Engine *ep, Const char *string);
參數ep為函數engOpen返回的引擎指標,字串string為要matlab執行的命令。
函數返回值為0表示成功執行,返回1說明執行失敗(如命令不能被Matlab正確解釋或Matlab引擎已經關閉了)。
3.7 擷取Matlab命令視窗的輸出
要在C中獲得函數engEvalString發送的命令字串被Matlab執行後在matlab視窗中的輸出,可以調用engOUtputBuffer函數。
函式宣告:
int engOutputBuffer(Engine *ep, char *p, int n);
參數ep為Matlab引擎指標,p為用來儲存輸出結構的緩衝區,n為最大儲存的字元個數,通常就是緩衝區p的大小。該函數執行後,接下來的 engEvalString函數所引起的命令列輸出結果會在緩衝區p中儲存。如果要停止儲存,只需調用代碼:engOutputBuffer(ep, NULL, 0)。
4 C調用Matlab quadprog函數介面樣本
/*Author:bangzhu.liDate:2014/09Instruction:This software program is only used as an example, not an error exception handling.E-mail:helpylee@126.com*/#include<stdio.h>#include<math.h>#include<stdlib.h>#include"engine.h"#include<string.h>int main(int argc,char** argv){ Engine *ep; if (!(ep = engOpen("\0"))) //啟動matlab 引擎 { fprintf(stderr, "\nCan't start MATLAB engine\n"); return EXIT_FAILURE; } engSetVisible(ep,false); mxArray *H = NULL, *f = NULL, *A = NULL, *b = NULL, *lb = NULL,*x = NULL; H = mxCreateDoubleMatrix(2, 2, mxREAL); f = mxCreateDoubleMatrix(2, 1, mxREAL); A = mxCreateDoubleMatrix(3, 2, mxREAL); b = mxCreateDoubleMatrix(3, 1, mxREAL); lb = mxCreateDoubleMatrix(2,1, mxREAL); x = mxCreateDoubleMatrix(2,1, mxREAL); double HH[2][2]={1,-1,-1,2}; double ff[2][1]={-2,-6}; double AA[3][2]={1,1,-1,2,2,1}; double bb[3][1]={2,2,3}; double llbb[2][1]={0,0}; double xx[2][1]={0,0}; //把C數群組轉換為Matlab數組 memcpy((void *)mxGetPr(H), (void *)HH, sizeof(double)*2*2); memcpy((void *)mxGetPr(f), (void *)ff, sizeof(double)*2*1); memcpy((void *)mxGetPr(A), (void *)AA, sizeof(double)*3*2); memcpy((void *)mxGetPr(b), (void *)bb, sizeof(double)*3*1); memcpy((void *)mxGetPr(lb), (void *)llbb,sizeof(double)*2*1); memcpy((void *)mxGetPr(x), (void *)xx,sizeof(double)*2*1); //把陣列變數寫入Matlab環境中 engPutVariable(ep, "H", H); engPutVariable(ep, "f",f); engPutVariable(ep,"A",A); engPutVariable(ep,"b",b); engPutVariable(ep,"lb",lb); engPutVariable(ep,"x",x); //執行字串命令 int ret1 = engEvalString(ep,"H = [1 -1; -1 2];"); int ret2 = engEvalString(ep,"f = [-2; -6];"); int ret3 = engEvalString(ep,"A = [1 1; -1 2; 2 1];"); int ret4 = engEvalString(ep,"b = [2; 2; 3];"); int ret5 = engEvalString(ep,"lb = zeros(2,1);"); int ret6 = engEvalString(ep,"[x] = quadprog(H,f,A,b,[],[],lb,[],[]);"); char p[256]={0}; char p1[256]={0}; char* ans = "disp(x(1,1));"; char* ans2 = "disp(x(2,1));"; engOutputBuffer(ep,p,240); engEvalString(ep,ans); printf("p:%s\n",p); engOutputBuffer(ep,p1,240); engEvalString(ep,ans2); printf("p1:%s,\n",p1); mxDestroyArray(H); mxDestroyArray(f); mxDestroyArray(A); mxDestroyArray(b); mxDestroyArray(x); engClose(ep); return 0;}
linux c 可以與matlab混編?
能,有linux c 與matlab混編的書,你在網上查一下,看看就能作出來了
在linux中,matlab與c混編遇到下面問題:
mex -setup過了嗎?
gcc版本太高,可以重新apt-get一個gcc4.2,然後替換掉gcc的符號連結。
缺少mexutils.h。