1、用C/C++編寫matlab函數(mexAdd.cpp)供後面測試用ios
#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); }
並在matlab中編譯:mex mexAdd.cpp數組
另幾列:app
/*================================================================= * mexfunction.c * * This example demonstrates how to use mexFunction. It returns * the number of elements for each input argument, providing the * function is called with the same number of output arguments * as input arguments. * This is a MEX-file for MATLAB. * Copyright 1984-2006 The MathWorks, Inc. * All rights reserved. *=================================================================*/ /* $Revision: 1.5.6.2 $ */ #include "mex.h" #pragma comment(lib,"libmx.lib") //#pragma comment(lib,"libmat.lib") #pragma comment(lib,"libmex.lib") void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]) { int i; /* Examine input (right-hand-side) arguments. */ mexPrintf("\nThere are %d right-hand-side argument(s).", nrhs); for (i=0; i<nrhs; i++) { mexPrintf("\n\tInput Arg %i is of type:\t%s ",i,mxGetClassName(prhs[i])); } /* Examine output (left-hand-side) arguments. */ mexPrintf("\n\nThere are %d left-hand-side argument(s).\n", nlhs); if (nlhs > nrhs) mexErrMsgTxt("Cannot specify more outputs than inputs.\n"); for (i=0; i<nlhs; i++) { plhs[i]=mxCreateDoubleMatrix(1,1,mxREAL); *mxGetPr(plhs[i])=(double)mxGetNumberOfElements(prhs[i]); } }
mat1.cide
#include"mex.h" void hilb(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; int n; if (nrhs!=1) mexErrMsgTxt("One inputs required."); if (nlhs != 1) mexErrMsgTxt("One output 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); n=mxGetM(plhs[0]); y=mxGetPr(plhs[0]); hilb(y,n); }
運行結果:函數
>> mex mat1.c >> a=mat1(10) a = 1.0000 0.5000 0.3333 0.2500 0.2000 0.1667 0.1429 0.1250 0.1111 0.1000 0.5000 0.3333 0.2500 0.2000 0.1667 0.1429 0.1250 0.1111 0.1000 0.0909 0.3333 0.2500 0.2000 0.1667 0.1429 0.1250 0.1111 0.1000 0.0909 0.0833 0.2500 0.2000 0.1667 0.1429 0.1250 0.1111 0.1000 0.0909 0.0833 0.0769 0.2000 0.1667 0.1429 0.1250 0.1111 0.1000 0.0909 0.0833 0.0769 0.0714 0.1667 0.1429 0.1250 0.1111 0.1000 0.0909 0.0833 0.0769 0.0714 0.0667 0.1429 0.1250 0.1111 0.1000 0.0909 0.0833 0.0769 0.0714 0.0667 0.0625 0.1250 0.1111 0.1000 0.0909 0.0833 0.0769 0.0714 0.0667 0.0625 0.0588 0.1111 0.1000 0.0909 0.0833 0.0769 0.0714 0.0667 0.0625 0.0588 0.0556 0.1000 0.0909 0.0833 0.0769 0.0714 0.0667 0.0625 0.0588 0.0556 0.0526 >>
2、安裝csh,不然在不能啓動matlab引擎即engOpen(NULL)始終返回0測試
sudo apt-get install tcshui
或spa
sudo apt-get install cshscala
3、建立一個目錄qtmatlab在下面放源文件main.cpp指針
#include <QtGui/QApplication> #include <QDebug> #include <cmath> #include <iostream> #include <engine.h> int main(int argc, char *argv[]) { // Test 1:將C++中的數據送入Matlab執行 // [1] 啓動Matlab引擎 Engine *ep = engOpen(NULL); if (!ep) { // 定義Matlab引擎指針,啓動引擎;失敗則返回NULL qDebug() << "Can't start Matlab engine!"; exit(-1); } engSetVisible(ep, false); // [2] 在C++內存空間構造須要計算或者畫圖的數據 const int N_SIZE = 10; double x[N_SIZE],y[N_SIZE]; for (int i=0; i<N_SIZE; i++) //計算數組x和y { x[i] = (i+1); y[i] = sin(x[i]); //產生正弦值 } // [3] 在C++內存空間定義Matlab數組 mxArray *xx = mxCreateDoubleMatrix(1,N_SIZE, mxREAL); // 定義mxArray,爲行,N_SIZE 列的實數數組 mxArray *yy = mxCreateDoubleMatrix(1,N_SIZE, mxREAL); // [4] 將數據拷貝到數組中 memcpy(mxGetPr(xx), x, N_SIZE*sizeof(double)); // 將數組x複製到mxarray數組xx中 memcpy(mxGetPr(yy), y, N_SIZE*sizeof(double)); // [5] 將C++內存空間的數據傳輸到Matlab引擎中 engPutVariable(ep, "xx",xx); // 將mxArray數組xx寫入到Matlab工做空間,命名爲xx engPutVariable(ep, "yy",yy); // [6] 執行Matlab引擎 engEvalString(ep, "plot(xx, yy); "); // 向Matlab引擎發送畫圖命令 // [7] 銷燬C++內存空間的數據 mxDestroyArray(xx); // 銷燬mxArray數組xx和yy mxDestroyArray(yy); // Test 2:顯示Matlab控制檯輸出信息 // [1] 將Matlab的輸出鏈接到buffer const int BUFSIZE = 1024; char buffer[BUFSIZE] = {'\0'}; engOutputBuffer(ep, buffer, BUFSIZE); // [2] 顯示Matlab裏數據的值 engEvalString(ep, "xx"); qDebug() << buffer; engEvalString(ep, "yy"); qDebug() << buffer; // Test 3:從Matlab引擎傳回數據 mxArray *_xx = engGetVariable(ep, "xx"); double *_x = mxGetPr(_xx); mxArray *_yy = engGetVariable(ep, "yy"); double *_y = mxGetPr(_yy); for (int i = 0; i < N_SIZE; i++) { qDebug() << "i=" << i << "|" << _x[i] << _y[i]; } // 銷燬mxArray數組_xx和_yy mxDestroyArray(_xx); mxDestroyArray(_yy); //Test 4:執行自定義函數(剛纔寫的那個函數) engEvalString(ep, "cd /home/mymotif/matlab_workplace; c = mexAdd(1,2)"); qDebug() << buffer; engClose(ep); //關閉Matlab引擎 return 0; }
4、編譯運行
qmake -project
產生qtmatlab.pro
編輯qtmatlab.pro追加下面兩行:
INCLUDEPATH += /opt/local/MATLAB/R2012a/extern/include
LIBS += -L"/opt/local/MATLAB/R2012a/bin/glnxa64" -leng -lmat -lmex -lmx -Wl,-rpath=/opt/local/MATLAB/R2012a/bin/glnxa64
其中的/opt/local/MATLAB/R2012a是MATLAB安裝路徑、須要根據實際環境修改
修改後的qtmatlab.pro內容以下:
###################################################################### # Automatically generated by qmake (2.01a) ?? 3? 16 19:58:53 2016 ###################################################################### TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . INCLUDEPATH += /opt/local/MATLAB/R2012a/extern/include LIBS += -L"/opt/local/MATLAB/R2012a/bin/glnxa64" -leng -lmat -lmex -lmx -Wl,-rpath=/opt/local/MATLAB/R2012a/bin/glnxa64 # Input SOURCES += main.cpp
qmake
make
./qtmatlab
5、testmat.c
//gcc-4.9 testmat.c -o testmat -I/opt/local/MATLAB/R2012a/extern/include -L/opt/local/MATLAB/R2012a/bin/glnxa64 -lm -leng -lmat -lmex -lmx #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; }
這裏只能用gcc4.x編譯,最新的gcc5.3會出錯
~$ ./testmat
p:>> 0.6667
p1:>> 1.3333
,