VC与Matlab混合编程

  • 格式:pdf
  • 大小:143.42 KB
  • 文档页数:5

VC与Matlab混合编程

本⽂主要介绍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引擎,绘制正弦曲线,相对简单,就不再详细解释,效图如下:

2. VC调⽤Matlab DLL的⽅式

DLL是⼀个可执⾏的⼆进制⽂件。把很多通⽤的功能放在DLL中,可以供各种应⽤程序调⽤,这样可以很好的减少外部存储空间的占有量,

并实现代码的共享。Matlab也⽀持将m程序编译成dll,供其他语⾔(包括VC、VB、Fortran等)调⽤,下⾯先简单介绍下Matlab DLL的编译步

骤:

2.1 Matlab DLL制作

(1)配置Matlab的编译器跟,要将mex和mbuil两个都配置成本机上安装的VC,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_CONVCaculateFun(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<<"Could not init lib !"<

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,因此需要分别介绍将结构体转换成这两种类