C与MATLAB混合编程(C语言中调用MATLAB)

一、用C/C++编写matlab函数(mexAdd.cpp)供后面测试用

#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

二、安装csh,否则在不能启动matlab引擎即engOpen(NULL)始终返回0

sudo apt-get install tcsh

sudo apt-get install csh

三、创建一个目录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;
 }

四、编译运行

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

五、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


,















你可能感兴趣的:(C与MATLAB混合编程(C语言中调用MATLAB))