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

另几列:

/*=================================================================
 * 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.c

#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

>> 

二、安装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

 

,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/u/2245781/blog/638863

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值