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
,