文档章节

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

wangxuwei
 wangxuwei
发布于 2016/03/16 22:57
字数 1437
阅读 394
收藏 1

一、用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

 

,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

© 著作权归作者所有

wangxuwei
粉丝 25
博文 335
码字总数 117394
作品 0
杭州
其他
私信 提问
Matlab编译C、C++程序的编译器配置

在进行Matlab、C或C++混合编程中,需要在Matlab中配置C、C++编译器,我的系统中装的是Matlab2012a和 Visual Studio2010,以这个为例,在Matlab中配置VS2010编译器。 首先在Matlab窗口中输入m...

Quincuntial
2015/04/13
0
0
多线程VC++和Matlab混编在信号采集和处理中的应用

引言 Visual C++自诞生以来,一直是Windows环境下最主要的应用开发系统,利用Visual C++开发系统可以完成各种应用程序的开发,从底层软件直到上层直接面向用户的软件都可以用Visual C++来...

云栖希望。
2017/12/04
0
0
Matlab调用C++代码的具体mex实现详解

在这里记录一下自己的挖坑、填坑过程。从mex环境到与成功调用 在具体的实现中,由于matlab具有很强的矩阵运算能力。而对于处理太多的循环结构运算却显得很吃力。所以在具体的实现中,我们可以...

sinat_38321889
2017/11/21
0
0
转]MATLAB 与 C 语言的接口

MATLAB 到 C 语言程序的转换可以由两种途径完成,其一是 MATLAB 自己提供的 C 语言翻译程序 mcc, 另一种是原第 3 方公司 MathTools 开发的 MATCOM。后者出现较早,功能远比 MATLAB 自己的翻译...

云栖希望。
2017/12/04
0
0
VC++与Matlab混合编程之引擎操作详解

Visual C++是当前主流的应用程序开发环境之一,开发环境强大,开发的程序执行速度快。但在科学计算方面函数库显得不够丰富、读取、显示数据图形不方便。Matlab是一款将数值分析、矩阵计算、信...

flyhighly
2010/12/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

JAVA 8 中新增 lambda 表达式的一些基本应用

import java.util.Arrays;import java.util.List;import java.util.function.Function;import java.util.stream.Collectors;public class TestLambda { public static void......

这是一只小小鸟
14分钟前
1
0
Java向word中插入Excel文件对象

前言: 在word文件中,虽然也有表格。但是有时我们想要将Excel中表格的大量数据直接插入到word文档中,这就需要用到word的插入对象的功能,也就是直接将Excel文件当做对象插入到word中。 本地的...

qianxi
16分钟前
2
0
海量数据下的注册中心 - SOFARegistry 架构介绍

SOFAStack Scalable Open Financial Architecture Stack 是蚂蚁金服自主研发的金融级分布式架构,包含了构建金融级云原生架构所需的各个组件,是在金融场景里锤炼出来的最佳实践。 SOFARegi...

SOFAStack
19分钟前
9
0
python操作excel表格

python 对excel的操作 提示:如果需要写多个表,需要把多个表写完在保存,否则会出现表格覆盖问题 此程序 采取一边请求,一边存取,做个异常处理,即可保存已存在的数据 """# sheet的名称,...

鹏灬
21分钟前
1
0
好程序员web前端分享如何理解JS的单线程

好程序员web前端分享如何理解JS单线程,JS本质是单线程的。也就是说,它并不能像JAVA语言那样,两个线程并发执行。 但我们平时看到的JS,分明是可以同时运作很多任务的,这又是怎么回事呢? ...

好程序员IT
25分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部