Linux 下C与matlab 混编

 1 概述

1.1 Matlab简介

   MATLAB是美国MathWorks公司出品的商业数学软件,用于算法开发、数据可视化、数据分析以及数值计算的高级技术计算语言和交互式环境,主要包括MATLABSimulink两大部分。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对如何编译Cmatlab 进行了说明,但是步骤较多,程序编译较为繁琐。因为我们可以通过一次环境变量的设置来达到这种目的。

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 MatlabC的接口函数介绍

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); 

参数mn为矩阵的函数和列数。ComplexFlag为常数,用来区分矩阵中元素是实数还是复数,取值分别为mxREALmxCOMPLEX

例如,创建一个35列的二维实数数组,可用如下语句:

mxArray *T = mxCreateDoubleMatrix(3, 5, mxREAL); 

对应的,要删除一个数组mxDestroyArray,该函数声明如下:

void mxDestroyArray(mxArray *array_ptr); 

参数array_ptr为要删除的数组指针。

 

类似的创建函数还有:

函数声明:

mxArray *mxCreateString(const char *str); 

创建一个字符串类型并初始化为str字符串。

一般的在CMatlab交互中,以上两种类型就够了,其它类型数组的创建这里不再介绍。

3.3 管理mxArray的数据类型

3.3.1 管理mxArray数据大小

要获得mxArray数组每一维上元素的个数,可以用mxGetMmxGetN函数。其中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数组中返回。对于常用的矩阵来说,用mxGetMmxGetN两个函数就可以了。

 

另外还可以通过mxGetNumberOfDimensions来获得数组的总的维数,用mxSetMmxSetN设置矩阵的行数和列数,函数说明如下:

 

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数组、整数、字符串、逻辑值等,以及是否为某种结构、类、或者是特殊类型,比如是否为空数组,是否为infNaN等。常见的判断函数有:

 

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类型的数组,可以用mxGetPrmxGetPi两个函数分别获得其实部和虚部的数据指针,这两个函数的声明如下:

 

double *mxGetPr(const mxArray *array_ptr); //返回数组array_ptr的实部指针

double *mxGetPi(const mxArray *array_ptr); //返回数组array_ptr的虚部指针 

这样,就可以通过获得的指针对mxArray类型的数组中的数据进行读写操作。例如可以用函数engGetVariableMatlab工作空间读入 mxArray类型的数组,然后用mxGetPrmxGetPi获得数据指针,对并其中的数据进行处理,最后调用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); 

参数epMatlab引擎指针,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;
}
 

 

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。