Matlab集成程序:matGear(仿真工程方面)
J-SUN-SO visualsan@yahoo.cn 2013.3 代码下载:
matlab作为一种强大的科学计算语言,其强大的计算能力和海量的函数工具包,把它作为后台计算语言嵌入到你的软件中去,可以省去繁杂的数学公式编程,是一种很好的计算资源。而matlab本身也提供了一组C语言API供程序调用。本文基于这组C语言API对MATLAB进行二次开发matGear,其目的只有一个:以更简便的方式,把MATLAB集成到自己的工程项目中去。
matlab引擎分为全局引擎和局部引擎。全局引擎只有一个,一旦启动全局引擎,则所有的计算结果和变量都是全局共享的。局部引擎是独立于线程的一个计算引擎,它的数据是局部拥有的,可以启动任意多的局部引擎,取决于计算机配置。启动一个局部引擎相当于开启一个独立的MATLAB线程,由于启动MATLAB是一个很耗时间的过程,因此应该尽量减少局部引擎的启动数量。
MEngine的结构如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
class MEngine { public: //初始化函数的bSingleUse=1表示启动一个局部引擎,bSingleUse=0表示启动全局引擎。 MEngine(BOOL bSingleUse=0);// bSingleUse=0启动全局引擎,计算空间数据共享 virtual ~MEngine(); BOOL IsEngineOpen();//是否候已经打开引擎 BOOL IsSingleUse();//是否是局部引擎 BOOL OpenEngine();//打开引擎 BOOL CloseEngine();//关闭引擎 void SetEngineVisible(BOOL bVisible);//设置引擎是否可见 BOOL GetEngineVisible(); void PutVar(char *name,MatlabData* d);//向MATLAB输入参数 BOOL GetVar(char *name,MatlabData** d);// 获取MATLAB参数 //执行命令 void EvalString(char* matlabString); const char* GetOutPut();//执行命令后的反馈输出 protected: Engine *m_matlabEng; int m_bInit; char m_OutBuffer[MAX_OUT_PUT];//局部matlab输出 static char g_OutBuffer[MAX_OUT_PUT];//全局malab输出 int m_bSingleUse;//是否独立开启一个matlab线程,否则将共享一个MATLAB线程。 };
bSingleUse=1表示启动局部引擎,bSingleUse=0表示启动全局引擎,全局引擎在第一次调用时打开MATLAB,以后没调用一次OpenEngine打开全局MATLAB,则引用计数加一;调用一次closeEngine引用计数减一。当引用计数为0时,表示当前没有程序对全局MATLAB进行调用,此时将自动关闭MATLAB。
调用void SetEngineVisible(BOOL bVisible)将决定是否显示MATLAB的窗口界面。函数void PutVar(char *name,MatlabData* d)将一个向MATLAB空间中添加一个自定义变量,其中name为变量名称,d为变量内容,若该变量已经存在,则调用该函数将覆盖已存在变量值。函数BOOL GetVar(char *name,MatlabData** d)将从MATLAB空间中提取一个变量,其中name为变量名称,d为输出指向内容指针的指针,若该变量已经存在,则发挥FALSE。
void EvalString(char* matlabString)可以和计算引擎进行命令交互,matlabString为命令,和常规使用MATLAB软件所进行的输入一致。一旦调用某个命令,MATLAB将有反馈输出,可能是计算结果,也可能是错误信息,这些信息可以通过调用const char* GetOutPut()来获取。
2. 数据类型
所有MATLAB和c语言的数据类型是mxArray,MATLAB提供了一组C语言API来进行数据操作。mxArray是一种包含多种类型的数据,可以是数值,字符,cell或者是结构体;数据类型可以是标量,矩阵或者是Array。
针对实际应用,将常用的数据类型进行接口设计。数据结构可分为标量,矩阵,阵列和结构体。数据类型有双精度浮点数,单精度浮点数,32位整数,64位整数,字符串。最后开发包装接口,实现类位mxWrap。mxWrap结构如下。mxWrap的构造函数提供了从标量、矩阵、阵列到字符的封装。根据不同的数据类型动态创建数据类型,从而实现了用单一接口类来操作不同数据类型。
测试函数:
/************************************************************************/ /* test matlab engine */ /************************************************************************/ static void TestEngine(); static void ArrayTest(); static void MatricTest(); //test matlab file write,you can check the file in matlab static void mat_file_write_test(std::string path="c:\\mat_test.mat");//mat文件测试 //read mat file test static void mat_file_read_test(std::string path="c:\\mat_test.mat"); //inout var to engine,run cmd and get result static void test1(); //Calculate Derivation static void cal_der(); //test mxWrap static void mxWrap_test(); //read the var name from mat file static void mat_var_name(std::string path="c:\\mat_test.mat");
void MatTest::TestEngine() { char *msg= "----Test For Matlab Engine!----------------------\n" "----Type any matlab cmd and type empty to exit!--\n" " visualsan@yahoo.cn 2013.3.9--\n" "-------------------------------------------------\n"; cout<<msg; MatEngine eng(0);//global engine cout<<"open engine.....\n"; if (!eng.OpenEngine()) { cout<<" fail to open matlab!\n"; return; } eng.SetEngineVisible(False); char cmd[500]; while (1) { cout<<">>"; cin>>cmd; if(strcmp(cmd,"exit")==0) { eng.CloseEngine(); return; } eng.EvalString(cmd); cout<<eng.GetOutPut()<<endl; } }
void MatTest::TestEngine() { char *msg= "----Test For Matlab Engine!----------------------\n" "----Type any matlab cmd and type empty to exit!--\n" " visualsan@yahoo.cn 2013.3.9--\n" "-------------------------------------------------\n"; cout<<msg; MatEngine eng(0);//global engine cout<<"open engine.....\n"; if (!eng.OpenEngine()) { cout<<" fail to open matlab!\n"; return; } eng.SetEngineVisible(False); char cmd[500]; while (1) { cout<<">>"; cin>>cmd; if(strcmp(cmd,"exit")==0) { eng.CloseEngine(); return; } eng.EvalString(cmd); cout<<eng.GetOutPut()<<endl; } }
ArrayTest()
void MatTest::ArrayTest() { char *msg= "----Test For Matlab Array data struct!----------------------\n" " visualsan@yahoo.cn 2013.3.9--\n" "-------------------------------------------------\n"; cout<<msg; mwSize sz[2]={2,3}; mwSize d=2; string str; #define TEST_TYPE(s) str=s;cout<<str.data(); TEST_TYPE("bool array test(bool阵列测试)\n"); bool ba1[]={false,true,false,false,true,false}; bool ba2[6]={false}; xArrayBool ba(d,sz,ba1); ba.GetRealData(ba2,6); int i=0; for (;i<6;i++) { cout<<ba1[i]<<"="<<ba2[i]<<" "; } cout<<endl; TEST_TYPE("char array test(char阵列测试)\n"); char ca1[]={'a','b','c','d','e','f'}; char ca2[6]={'0'}; xArrayChar ca(d,sz,ca1); ca.GetRealData(ca2,6); for ( i=0;i<6;i++) { cout<<"'"<<ca1[i]<<"'='"<<ca2[i]<<"' "; } cout<<endl; TEST_TYPE("double array test(double阵列测试)\n"); double da1[]={100.0,200.0,300.0,400.0,500.0,600.0}; double da2[6]={'0'}; xArrayDouble da(d,sz,da1); da.GetRealData(da2,6); for ( i=0;i<6;i++) { cout<<da1[i]<<"="<<da2[i]<<" "; } cout<<endl; TEST_TYPE("float array test(float阵列测试)\n"); float fa1[]={1010.0,2010.0,3010.0,4010.0,5010.0,6010.0}; float fa2[6]={'0'}; xArrayFloat fa(d,sz,fa1); fa.GetRealData(fa2,6); for ( i=0;i<6;i++) { cout<<fa1[i]<<"="<<fa2[i]<<" "; } cout<<endl; TEST_TYPE("int array test(int阵列测试)\n"); int ia1[]={101,201,301,401,501,601}; int ia2[6]={'0'}; xArrayInt ia(d,sz,ia1); ia.GetRealData(ia2,6); for ( i=0;i<6;i++) { cout<<ia1[i]<<"="<<ia2[i]<<" "; } cout<<endl; NOTE_IN_END; }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
void MatTest::MatricTest() { char *msg= "----Test For Matlab Matrix !----------------------\n" " visualsan@yahoo.cn 2013.3.9--\n" "-------------------------------------------------\n"; cout<<msg; double dm1[]=//2*5 { 11,12,13,14,15, 21,22,23,24,25 }; //change c++ matrix style to matlab matrix style xMatrixDouble::C2Mat(dm1,2,5,dm1); double dm2_r[10]; double dm2_i[10]; //a 2X5 matrix xMatrixDouble dm(2,5,dm1,dm1,mxCOMPLEX); dm.GetRealData(dm2_r,10);//get real data dm.GetImgData(dm2_i,10);//get complex data cout<<"input real :\n"; int i=0; for (;i<10;i++) { cout<<dm2_r[i]<<" "; }cout<<"\nmatrix real:\n"; for (i=0;i<dm.GetR();i++) { for (int k=0;k<dm.GetC();k++) { cout<<dm.GetRealAt(i,k)<<" "; } cout<<endl; } cout<<"\ninput img:\n"; for ( i=0;i<10;i++) { cout<<dm2_i[i]<<" "; } cout<<"\nMatrix-real(matlab是按列存储的)\n"; for (i=0;i<dm.GetR();i++) { for (int j=0;j<dm.GetC();j++) { cout<<dm.GetImgAt(i,j)<<" "; } cout<<endl; } cout<<"(1,1)="<<dm.GetRealAt(1,1)<<"+"<<dm.GetImgAt(1,1)<<"i"<<endl; cout<<"(1,1)changed:\n"; dm.SetRealAt(1,1,12.111); dm.SetImgAt(1,1,22.111); cout<<"(1,1)="<<dm.GetRealAt(1,1)<<"+"<<dm.GetImgAt(1,1)<<"i"<<endl; NOTE_IN_END; }
write mat file
void MatTest::mat_file_write_test(std::string path)//mat文件测试 { cout<<"===========写mat文件测试====================\n"; xFile f; mxWrap d(12.0); if(0==f.Open((char*)path.c_str(),"w")) { cout<<"打开文件失败\n"; return ; } xDouble v1(123.0); //add double f.SetArray("double_v",&mxWrap(v1.GetArray())); //replace double var wit string var xString v11("double_v——通过测试"); f.SetArray("double_v",&mxWrap(v11.GetArray())); //add float var xFloat v2(223.0); f.SetArray("xFloat_v",&mxWrap(v2.GetArray())); //add string var xString v3("xString"); f.SetArray("xString_v",&mxWrap(v3.GetArray())); //替换测试 xString v31("xString——通过测试"); f.SetArray("xString_v",&mxWrap(v3.GetArray())); //add bool var xBool v4(1); f.SetArray("xBool_v",&mxWrap(v4.GetArray())); //add int var xInt v5(1569); f.SetArray("xInt_v",&mxWrap(v5.GetArray())); //add UINT var xUInt v6(136); f.SetArray("xUInt_v",&mxWrap(v6.GetArray())); xInt64 v7(64); f.SetArray("xInt64_v",&mxWrap(v7.GetArray())); xUInt64 v8(164); f.SetArray("xUInt64_v",&mxWrap(v8.GetArray())); //add matrix double dt[8]={1,2,3,4,5,6,7,8}; xMatrixDouble v9(2,4,dt); f.SetArray("xMatrixDouble_v",&mxWrap(v9.GetArray())); //add array mwSize dm[3]={2,2,2}; xArrayDouble v10(3,dm,dt); f.SetArray("xArrayDouble_v",&mxWrap(v10.GetArray())); //add struct xStruct xs; xs.AddField("double_number"); xs.AddField("who_is"); xs.SetField(0,new mxWrap(120.364)); xs.SetField(1,new mxWrap("The type_info class describes type information generated within the program by the compiler. Objects of this class effectively store a pointer to a name for the type and an encoded value suitable for comparing two types for equality or collating order. The encoding rules and collating sequence for types are unspecified and may differ between programs.")); f.SetArray("xstruct",&mxWrap(xs.GetArray())); ///删除变量 if(f.RemoveVar("xInt_v"))cout<<"成功删除变量!\n"; if(f.RemoveVar("xMatrixDouble_v"))cout<<"成功删除变量!\n"; if(0==f.RemoveVar("不存在的名称")) cout<<"删除不存在变量失败!\n"; f.Close(); cout<<"success write mat file\nuse matlab to check the file\n"; NOTE_IN_END; }
read mat file
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
void MatTest::mat_file_read_test(std::string path) { //从mat文件读取变量测试 xFile f; mxWrap d(12.0); if(!f.Open((char*)path.c_str(),"r")) { cout<<"cant open file\n"; return; } for (int i=0;i<f.GetVarCount();i++) { std::string n; ImxArray*ptr=f.GetArray(i,&n)->GetArrayInterface(); cout<<"============================"<<n.data()<<ptr->GetType()<<endl; display_data(ptr,n); //struct if(ptr->GetType()==MX_DATA_STRUCT) { cout<<" struct=====================\n"; xStruct*ps=(xStruct*)ptr; for (int h=0;h<ps->GetFieldCount();h++) { cout<<ps->GetFieldName(h).data()<<"=======\n"; char tmp[200]; strcpy(tmp,ps->GetFieldName(h).data()); n=std::string(tmp); display_data(ps->GetField(h)->GetArrayInterface(),n); } } } f.Close(); NOTE_IN_END; }
input and get var
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
void MatTest::test1() { MatEngine g; cout<<"open engine.....\n"; g.OpenEngine(); //MATRIX A double A[]= { 1,2,3, 4,5,6, 7,8,9 }; xMatrixDouble::C2Mat(A,3,3,A); //MATRIX B double B[]= { 11,21,31, 41,51,61, 71,81,91 }; xMatrixDouble::C2Mat(B,3,3,B); //VAR A and B mxWrap a(3,3,A); mxWrap b(3,3,B); //PUT VAR g.PutVar("A",a.GetArray()); g.PutVar("B",b.GetArray()); //CAL g.EvalString("C=A*B"); //get val mxWrap c; g.GetVar("C",&c); //disp data xMatrixDouble*ptr=(xMatrixDouble*)c.GetArrayInterface(); cout<<"C=A*B\n"; for (int i=0;i<ptr->GetR();i++) { for (int j=0;j<ptr->GetC();j++) { cout<<ptr->GetRealAt(i,j)<<" "; } cout<<endl; } g.CloseEngine();//close NOTE_IN_END; }
use engine sample
void MatTest::cal_der() { MatEngine eng; cout<<"open engine.....\n"; eng.OpenEngine(); eng.SetEngineVisible(0); char tmp[200];//表达式 char tmp1[200]; mxWrap df;//导数表达式 mxWrap val;//原函数值 mxWrap dfval;//导数值 xDouble vx0;//x0 输入 double x0=0; int n=1;//导数阶数 strcpy(tmp,"syms x;"); eng.EvalString(tmp); cout<<"输入表达式(et. y=sin(x) ):"; cin>>tmp; cout<<"输入导数阶数(et. 2):"; cin>>n; cout<<"输入x0(et. 10):"; cin>>x0; vx0.SetRealData(x0); while( tmp[0] != 'q' ) { eng.PutVar("x0",vx0.GetArray());//input x0 //get express sprintf(tmp1,"%s;z1=diff(y,%d),z=char(z1),val=subs(y,x,x0),dfval=subs(z,x,x0)",tmp,n); //cal eng.EvalString(tmp1); //get val eng.GetVar("z",&df);//n阶导数表达式 eng.GetVar("val",&val);//原函数在x0处的数值 eng.GetVar("dfval",&dfval);//n阶导数在x0处的数值 // cout<<"---------------------------matlab output----------------\n"; // cout<<eng.GetOutPut()<<endl; // cout<<"---------------------------------------------------------\n"; cout<<"---------------------------求导结果----------------\n"; xString*ps=(xString*)df.GetArrayInterface(); cout<<"求导结果:"<<ps->GetString().data()<<endl; xDouble*pd=(xDouble*)val.GetArrayInterface(); cout<<"原函数在x0处的值:"<<pd->GetRealData()<<endl; pd=(xDouble*)dfval.GetArrayInterface(); cout<<"原函数导n阶数在x0处的值:"<<pd->GetRealData()<<endl; cout<<"----------------------------------------------------\n"; cout<<"输入表达式:"; cin>>tmp; cout<<"输入导数阶数:"; cin>>n; cout<<"输入x0:"; cin>>x0; vx0.SetRealData(x0); } eng.CloseEngine(); }
mat file var list
void test4() { xFile xf; if (xf.Open("C:\\Documents and Settings\\Administrator\\桌面\\SWING\\mexTest\\mexTest\\Debug\\dC.mat","r")) { cout<<"变量个数:"<<xf.GetVarCount()<<endl; std::vector<mxWrap*> var; std::vector<std::string> vname; for (int i=0;i<xf.GetVarCount();i++) { std::string name; var.push_back(xf.GetArray(i,&name,1)); vname.push_back(name); //输出名称 printf("var name(%2d)=%20s\n",i+1,name.data()); } //输出每个变量 for(i=0;i<var.size();i++) { display_data(var[i]->GetArrayInterface(),vname[i]); } } }
mawrap test
void MatTest::mxWrap_test() { int dA[]= { 1 ,2 ,3, 4 ,5 ,6, 7 ,8 ,9 }; xMatrixInt::C2Mat(dA,3,3,dA); mxWrap A(3,3,dA); mxWrap B("南京航空航天大学 san visualsan@yahoo.cn"); xStruct* xs=new xStruct; //add field xs->AddField("name"); xs->AddField("address"); xs->AddField("score"); xs->AddField("matrix"); mxWrap*ptr; ptr=new mxWrap("san"); xs->SetField(0,ptr);//add name ptr=new mxWrap("NUAA"); xs->SetField(1,ptr);//add address ptr=new mxWrap(99.9); xs->SetField(2,ptr);//add score double m[]={12 ,22, 32}; xMatrixDouble::C2Mat(m,1,3,m); ptr=new mxWrap(1,3,m);; xs->SetField(3,ptr);//add matrix mxWrap C(xs); mxWrap D(123.00); mxWrap E(100); xFile xf; //OPEN FILE and write var to file.you can check file in matlab xf.Open("c:\\result.mat","w"); //ADD VAR xf.SetArray("A",&A); xf.SetArray("B",&B); xf.SetArray("C",&C); xf.SetArray("D",&D); xf.SetArray("E",&E); //CLOSE xf.Close(); mat_file_read_test("c:\\result.mat"); }
源代码链接:http://www.pudn.com/downloads519/sourcecode/app/detail2153519.html