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.li Date:2014/09 Instruction:This software program is only used as an example, not an error exception handling. E-mail:[email protected] */ #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; }