本文主要介绍VC与Matlab混合编程的两种方法,并详细介绍了VC向Matlab传递复杂数据:结构体的方法,有详细代码说明。

Matlab 主要面对科学计算、可视化以及交互式程序设计的高科技计算环境,但由于Matlab开发平台上开发的程序不能脱离Matlab运行环境,因而在处理一些实际应用问题时显得灵活性不足,而VC++则在一定程度上能够弥补这一漏洞,因此,将二者结合共用,各献其长,可以为科研工作和工程开发提供更为强大的技术支持。

Matlab作为控制系统设计的一种通用工具,它可以很方便的和VC进行连接。一般而言,Matlab与VC混合编程的实现方法有很多种,这里主要介绍以下两种:

1            VC调用Matlab Engine的方式:

Matlab Engine是一组Matlab提供的接口函数,支持C/C++语言,Matlab Engine采用C/S(客户机/服务器)模式,Matlab作为后台服务器,而C/C++程序作为前台客户机,向Matlab Engine传递执行命令和数据信息,从Matlab Engine接收执行结果。用户可以在前台应用程序中调用这些接口函数,实现对Matlab Engine的控制。采用这种方法几乎能利用Matlab全部功能,但是需要在机器上安装Matlab软件,缺点是执行效率较低。下面简单介绍下这种方式的实现步骤:

1.1         API接口介绍

先来介绍一组Matlab提供的引擎API接口:(仅作简单功能介绍,详细参数说明请参考Matlab帮助)

Engine* engOpen(const char* startcmd)启动Matlab引擎

int engClose(Engine* ep) 关闭Matlab引擎

int engEvalString(Engine* ep, const char* string)执行Matlab表达式

mxArray* engGetArray(Engine* ep, const char* name)获取一个变量数组的值

int engPutArray(engine* ep, const mxArray* mp)设置一个变量数组的值

int engPutVariable(Engine *ep, const char *name, const mxArray *pm)同上

mxArray *engGetVariable(Engine *ep, const char *name)获取一个变量

int engOutputBuffer(Engine* eP,char* p,int n)获取输出字符串

1.2         VC环境配置

要想在VC集成环境下调用Matlab引擎实现VC和Matlab的混合编程,一般需要经过以下几个必要的步骤:(以下以Matlab2008a和VS2005版本为例)

(1)添加include路径:将“\extern\include”(在Matlab的安装路径下)路劲添加到VC编译器的include下

(2)添加lib路径:将“\extern \lib\win32\microsoft” (在Matlab的安装路径下) 路径添加到VC编译器的lib下

(3)加载lib:需要加载至少libmx.lib、libmat.lib、libeng.lib三个库

(4)include头文件:在要使用 engine 函数的地方包含engine.h头文件

1.3         引擎调用

接下来就可以在VC中调用Matlab引擎了,简单的示例代码如下:

#include "engine.h"

#pragma comment(lib, "libeng.lib")

#pragma comment(lib, "libmx.lib")

#pragma comment(lib, "libmat.lib")

void TestDeno()

{

Engine* pEng = NULL;

if (!(pEng = engOpen(NULL)))

{

printf("Open matlab enging fail!");

return;

}

//call Engine plot A*sin(t)+B A=2 B=1    mxArray *A = NULL;

double init = 2;

A = mxCreateDoubleMatrix(1, 1, mxREAL);

memcpy((void*) mxGetPr(A), (void*)&init, sizeof (double));

engPutVariable(pEng, "A", A);

init = 1;

memcpy((void*) mxGetPr(A), (void*)&init, sizeof (double));

engPutVariable(pEng, "B", A);

mxDestroyArray(A);

Sleep(3*60*1000);

engEvalString(pEng, "t=0:0.2:7;plot(t,A*sin(t)+B);");

if(NULL != pEng)

{

engClose(pEng);

}

}

示例代码通过VC调用Matlab引擎,绘制正弦曲线,相对简单,就不再详细解释,效图如下:(注意这里A、B的赋值方式,后续还会提及)

2            VC调用Matlab DLL的方式:

DLL是一个可执行的二进制文件。把很多通用的功能放在DLL中,可以供各种应用程序调用,这样可以很好的减少外部存储空间的占有量,并实现代码的共享。Matlab也支持将m程序编译成dll,供其他语言(包括VC、VB、Fortran等)调用,下面先简单介绍下Matlab DLL的编译步骤:

2.1         Matlab DLL制作

(1)配置Matlab的编译器跟,要将mex和mbuil两个都配置成本机上安装的VC,关于mex编译器的配置参见上一篇博文《S-Function实现simulink》,mbuild的配置方法同mex

(2)编译m函数成为dll,在matlab命令空间中使用mcc命令编译m文件:(mcc的使用参考Matlab帮助)

示例:将一个Matlab函数MyFun 编译成libMyFun 的命令:

mcc –W cpplib:libMyFun –T link:lib MyFun

参数说明:-W控制编译之后的封装格式,cpplib表示c++的lib,冒号之后是编译输出lib名,-T表示目标,link:lib表示连接到lib的目标,MyFun是待编译的m文件名,编译成功之后,会输出三个文件:libMyFun.lib libMyFun.dll libMyFun.h

2.2            DLL在VC中调用

要想在VC集成环境下调用Matlab的DLL,实现VC和Matlab的混合编程,一般需要经过以下几个必要的步骤:(以下以Matlab2008a和VS2005版本为例)

(1)VC环境配置,同前面VC调用Matlab引擎方式类似,也需要配置VC的编译环境,其中include路径、lib路径和前一种方式相同,加载的lib变更为:mclmcrrt.lib、libmx.lib、libmat.lib、mclmcr.lib四个,include的头文件变更为: mclmcr.h、matrix.h、mclcppclass.h三个。

(2)DLL中函数的调用,先看一下m函数编译成C++Dll之后的函数声明,例:matlab函数:function [y, out] = CaculateFun(x, in)编译之后对应c++的声明:void MW_CALL_CONV CaculateFun(int nargout, mwArray& y, mwArray& out, const mwArray& x, const mwArray& in)参数int nargout指定调用时,输出参数的个数,紧跟的后续nargout个参数y、out为输出参数,后续再剩下的多个参数x、in就为输入参数。

(3)注意事项:在VC中调用dll中的函数之前,需要先调用函数libFunInitialize初始化,在调用完函数以后,需要再调用函数libFunTerminate和mclTerminateApplication终止。

准备好了上述步骤,就可以在VC中调用DLL中函数的了,简单的示例代码如下:

// include matlab sys head file#include "mclmcr.h"

#include "matrix.h"

#include "mclcppclass.h"

// include lib head file#include "libCaculateFun.h"

// link matlab sys lib#pragma comment(lib, "mclmcrrt.lib")

#pragma comment(lib, "libmx.lib")

#pragma comment(lib, "libmat.lib")

#pragma comment(lib, "mclmcr.lib")

// link lib#pragma comment(lib, "libCaculateFun.lib")

void TestDeno()

{

// init lib    if (!(libCaculateFunInitialize()))

{

std::cout<

return -1;

}

double xxxx[2] = {0};

double inin    = 0;

double yyyy[2] = {0};

double outo    = 0;

// 为函数参数分配内存空间    mwArray mwXX(1, 2, mxDOUBLE_CLASS);

mwArray mwIn(1, 1, mxDOUBLE_CLASS);

mwArray mwYY(1, 2, mxDOUBLE_CLASS);

mwArray mwOut(1, 2, mxDOUBLE_CLASS);

// 为输入参数赋值    mwXX.SetData(&xxxx, 2);

mwIn.SetData(&inin, 1);

// 调用计算函数    CaculateFun(2, mwYY, mwOut, mwXX, mwIn);

// 获取输出参数    outo = mwOut.Get(1, 1);

// lib Terminate    libCaculateFunTerminate();

// MCR Terminate    mclTerminateApplication();

}

示例代码通过VC调用Matlab DLL,将变量xxxx的值付给yyyy,将变量inin的值付给outo,相对简单,就不再详细解释,(注意这里函数参数的赋值方式,后续还会提及)

3            Vc向Matlab函数传递参数

前面在介绍两种混合编程的方式时,示例代码中已经涉及到了参数的传递问题,对于VC中的简单数据类型:变量、数组等,网上已经有很多资料介绍,前面示例代码中也有所体现,这里不再详细说明。

关于复杂数据结构:用户自定义结构体类型,处理起来比较麻烦,网上能找到的资料也较少,由于前面提及的两种方式,在传递参数时,使用的数据类型是不一致的:引擎方式只能是mxArray类型,而DLL方式的参数只能是mwArray,因此需要分别介绍将结构体转换成这两种类型的方法:

先来定义两个结构体:// 三维坐标系中的点struct Postion

{

double x;

double y;

double z;

};// 名字标示的一个坐标点struct Coordinate

{

struct Postion pos;

char name[ARRAYSIZE];

};

分别介绍将如上两个结构体转成Matlab能使识别的Array的方法

(1)    结构体转换成mxArray:解释比较多余,就直接上代码吧:

mxArray *Staruct2mxArray(struct Postion *pStaruct)

{

mxArray *pm, *mx;

mwSize m = 1, n = 1;

const int nfields = 3;

const char *fieldnames[3] = {"x","y","z"};

const mwIndex index = 0;

pm = mxCreateStructMatrix(m, n, nfields, fieldnames);

mx = mxCreateNumericMatrix(m, n, mxDOUBLE_CLASS, mxREAL);

memcpy(mxGetPr(mx), &(pStaruct->x), sizeof(double));

mxSetFieldByNumber(pm, index, 0, mx);

mx = mxCreateNumericMatrix(m, n, mxDOUBLE_CLASS, mxREAL);

memcpy(mxGetPr(mx), &(pStaruct->y), sizeof(double));

mxSetFieldByNumber(pm, index, 1, mx);

mx = mxCreateNumericMatrix(m, n, mxDOUBLE_CLASS, mxREAL);

memcpy(mxGetPr(mx), &(pStaruct->z), sizeof(double));

mxSetFieldByNumber(pm, index, 2, mx);

return pm;

}

mxArray *Staruct2mxArray(struct Coordinate *pStaruct)

{

mxArray *pm, *mx;

mwSize m = 1, n = 1;

const int nfields = 2;

const char *fieldnames[2] = {"pos","name"};

const mwIndex index = 0;

pm = mxCreateStructMatrix(m, n, nfields, fieldnames);

mx = Staruct2mxArray(&(pStaruct->pos));

mxSetFieldByNumber(pm, index, 0, mx);

n = ARRAYSIZE;

mx = mxCreateNumericMatrix(m, n, mxCHAR_CLASS, mxREAL);

memcpy(mxGetPr(mx), pStaruct->name, sizeof(char)*ARRAYSIZE);

mxSetFieldByNumber(pm, index, 1, mx);

return pm;

}

(2)    结构体转换成mwArray:

mwArray Staruct2mwArray(struct Postion *pStaruct)

{

mwSize m = 1, n = 1;

const int nfields = 3;

const char *fieldnames[3] = {"x","y","z"};

mwArray pm(m, n, nfields, fieldnames);

mwArray mx(pStaruct->x);

pm(fieldnames[0], 1, 1) = mx;

mwArray my(pStaruct->y);

pm(fieldnames[1], 1, 1) = my;

mwArray mz(pStaruct->z);

pm(fieldnames[2], 1, 1) = mz;

return pm;

}

mwArray Staruct2mwArray(struct Coordinate *pStaruct)

{

mwSize m = 1, n = 1;

const int nfields = 2;

const char *fieldnames[2] = {"pos","name"};

const mwIndex index = 0;

mxArray pm(m, n, nfields, fieldnames);

mxArray mpos = Staruct2mwArray(&(pStaruct->pos));

pm(fieldnames[0], 1, 1) = mpos;

mxArray mname(pStaruct->name);

pm(fieldnames[1], 1, 1) = mname;

return pm;

}

(3)    mxArray转换成结构体:

struct Coordinate *mwArray2Staruct(mwArray pm)

{ // 代码仅处理 name 字段 pos 字段是三个简单类型省略    struct Coordinate *pStaruct = new struct Coordinate;

const int nfields = 2;

const char *fieldnames[2] = {"pos","name"};

mwArray mwStr = pm.Get(fieldnames[1], 1, 1);

char *str = strdup(mwStr.ToString());

memcpy(pStaruct->name,str,sizeof(char)*ARRAYSIZE);

return pStaruct;

}

(4)    mwArray转换成结构体:

struct Coordinate *mxArray2Staruct(mxArray *pm)

{ // 代码仅处理 name 字段 pos 字段是三个简单类型省略    struct Coordinate *pStaruct = new struct Coordinate;

mxArray * mxname = mxGetFieldByNumber(pm, 1, 1)

mxArray * str = mxGetPr(mxname);

memcpy(pStaruct->name,str,sizeof(char)*ARRAYSIZE);

return pStaruct;

}

matlab 不同函数间传递结构体数据_VC与Matlab混合编程及复杂数据:结构体传递相关推荐

  1. matlab输出lccde_Matlab与Visual C++混合编程处理全站仪数据的方法

    Matlab 与 Visual C++ 混合编程处理全站仪数据的方法 胡加星,刘立龙,刘靖晔 [摘 要] 内业数据检核中经常要对点的外业实测坐标与内业成图后的坐标进行 比较,以此来发现是否出现造点或是 ...

  2. matlab plot函数_慧图大讲堂 | 一起来认识MATLAB吧!

    慧图大讲堂 岁月流转,时光飞逝.转眼间又开学了,小伙伴们在使用MATLAB吗?想知道漂亮的图表.还原模糊图像.图像识别.模型预测,这些好玩的东西怎么做?快点和慧图君一起认识MATLAB吧! 01 什么 ...

  3. matlab中函数或变量无法识别怎么办_用MATLAB巧解微分方程实例分析

    点"考研竞赛数学"↑可每天"涨姿势"哦! MATLAB巧解微分方程实例分析 王少华 西安电子科技大学 微分方程求解难, 字母一堆看着烦. 写错数字一时爽, 一直 ...

  4. matlab 不同函数间传递结构体数据_matlab 结构体struct函数使用方法

    1.struct函数直接定义 查阅文档是这样的:struct(field1,value1,field2,value2,.....) 上面这个格式很重要记住 field1和field2称为这个结构体的字 ...

  5. matlab db函数_图灵斑图与反应扩散方程——Matlab的实现

    假设我们在做一个化学反应实验,存在U和V两种化学物质,其中每单位U物质在两单位V物质的催化下,生成新的V物质.那么V物质的浓度将会发生怎样的变化? 设想一下,随着时间的推移,反应皿中 V物质的浓度应该 ...

  6. matlab 狄利克雷函数图像,Poisson image editing算法实现的Matlab代码解析

    之前我发了数篇系列博文来仔细研究Poisson Image Editing算法,每次重新审视和深入,仿佛都能有更为深刻的认识和很大的收获.这应该算是我这个系列的完结篇,会用用Matlab代码一点一点的 ...

  7. matlab disp函数_代码 | 求解LP问题单纯形法的Matlab代码

    介绍求解LP问题最优解的Matlab代码. Contents 求LP问题的基本(可行)解Matlab代码 基本原理 Matlab代码 初始化 是否随机生成LP问题还是自己指定LP问题 初始化系数矩阵A ...

  8. Java设计模式中组合模式是什么/树形结构怎么组合或显示存储,编程怎么实现树形结构

    继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库Java设计模式克隆下载学习使用! 5.7 组合模式 5.7.1 概述 又名整体模式,是用于把一组相似的对象当作一个单一的对象 依据树形结构 ...

  9. matlab中怎么求函数的最小值,matlab求函数的最小值

    将上述各函数值进行比较,最终确定出在 D 内的最大值和最小值. 3.函数求偏导数的 MATLAB 命令 MATLAB 中主要用 diff 求函数的偏导数,用 jacobian 求 ...... 第七讲 ...

  10. matlab 定义函数 调用,matlab 定义函数,matlab定义函数并调用

    matlab 定义函数,matlab定义函数并调用,Matlab自定义函数详解 很久以前写的一篇Matlab自定义函数访问量很大,可惜没有点赞的,我感觉是我没讲清楚,这里又写了一篇笔记 Matlab函 ...

最新文章

  1. Access restriction: The type Unsafe is not accessible due to restriction on required library
  2. tensorflow tf.py_func
  3. WIN10系统触摸板快捷键
  4. lucene索引word/pdf/html/txt文件及检索(搜索引擎)
  5. 45道CSS基础面试题
  6. Kunpeng BoostKit 使能套件:大数据场景如何实现“大鹏一日同风起”倍级性能提升?
  7. ggplot2实现分半小提琴图绘制基因表达谱和免疫得分
  8. IPv6下网络编程实例
  9. js constructor 和 instanceof
  10. 【Unity】添加 Device Simulator功能
  11. 小米笔记本安装原生win7
  12. 超声成像突破衍射极限,有望检测肿瘤
  13. 为知笔记的markdown图片处理
  14. WebRTC音频降噪使用
  15. word文档无法保存问题
  16. 粒子能量、量子波动方程、狄拉克方程、量子态【量子力学基础知识学习笔记_3】
  17. zip和tgz以及exe的区别
  18. zz在Excel中作ROC曲线
  19. JAVA一些实例实战
  20. Cobalt Strike Beacon 初探

热门文章

  1. 计算机科学与技术的班会,计算机科学与技术学院2014级信管三班班会
  2. 4g网络切换软件_游戏掉线坑队友?OPPO Reno网络切换超快,上分吃鸡更稳
  3. java jquery分页_如何最简单的实现java分页
  4. 容器技术Docker K8s 18 容器服务ACK基础与进阶-容器网络管理
  5. Google Code Review在代码审查中寻找什么
  6. html扩展名用于保存清单文件,html5 – HTML 5缓存清单是否也适用于ajax请求?
  7. 282.给表达式添加运算符
  8. 反向传播算法BP公式推导
  9. Java反射机制--反射概述
  10. easyui tree json php,easyui tree json