当前位置:文档之家› Matlab与C_C_的接口及其在仿真中的应用

Matlab与C_C_的接口及其在仿真中的应用

Matlab与C_C_的接口及其在仿真中的应用
Matlab与C_C_的接口及其在仿真中的应用

文章编号:1671-

637ò(2002)04-0040-05

Matlab 与C /C ++的接口及其在仿真中的应用

周正人, 张凤霞, 赵振宇

(中国航空工业洛阳电光设备研究所,河南洛阳 471009)

摘 要: 介绍了如何利用Matlab 与C /C ++的接口将现有的C 程序代码导入到Matlab 中

使用,以及将Matlab 的m 文件导出到VC 中,从而可以利用Matlab 和VC 的各自优势进行仿真软件的开发。这能够大大提高开发效率。

关 键 词: Matlab; 接口; m 文件; 仿真中图分类号: TP 31; TP 39 文献标识码: B

Matlab C /C ++interface and its

application in simulation

ZHOU Zheng-ren, ZHANG Feng-xia, ZHAO Zhen-yu

(Luoyang I nstitute of E lectro -optical Equipment , Luoyang 471009, China )

Abstract : This paper introduces how to import current C codes to Matlab and export Matlab m files to VC by the Matlab C/C++interface.In this way,simulation software can be developed with the integrated superiority of Matlab and VC ,and the developing efficiency can be increased .Key Wor ds : Matlab ; interface ; m file ; simulation

0 引言

Matlab 是个功能完善的自包容程序设计和数据处理集成环境,在科学运算、数据处理、系统分析、控制系统和科学绘图领域,使用Matlab 具有非常明显的优势。使用它提供的功能、内建函数以及工具箱,无需借助外界的任何帮助,就可高效完成任务。在这个环境中,只需寥寥数语就可以完成十分复杂的功能,在易学易用、编程效率、可读性、可移植性和可扩充性上,Matlab 更是远远胜于其它高级编程语言。

Matlab 的功能非常强大,但也不是完美无缺的。现有的很多大型程序是用C /C ++语言编写的,

不可能完全使用Matlab 语言改写。首要的问题是代

码重用问题;其次,Matlab 作为一种以解释方式执

行的高级计算机语言,其执行效率是较低的,而在火

控解算时需要高效率的执行代码,这样又碰到了执

行效率的问题;Matlab 中的变量不需要事先声明就

可以直接使用,其调试环境的调试功能也不够强大。不过,这些问题Matlab 都通过它的外部接口一一解决了。

在火控系统解算中,许多量都可以使用矢量来

表示,因此可以使用矢量方程法来进行航空火力控制问题的解算。利用矢量方程法解算火控问题,简明扼要,推导严密,适用于解算任意复杂的航空火力控

制问题。所以,可以利用Matlab 强大的矢量和矩阵

收稿日期:2002-01-23

作者简介:周正人(1976-),男,广西兴安人,学士,助理工程师,主要从事火控总体技术研究。

Vol.9 №.4Nov.2002 电光与控制ELECT RONICS OP TICS &CONT ROL

第9卷 第4期

2002年11月

运算功能,来完成火控解算中的矢量运算或者火控系统的仿真,并且可以用其C++数学库把Matlab 的非脚本m文件转化为C++源文件,然后将其嵌入VC工程中进行编译。这样可以利用两者长处进行互补,达到事半功倍的效果。

1 Matlab与C/C++的接口及应用

1.1 概述

Matlab为了解决上述问题,提供了外部接口,本文主要介绍它与C/C++的接口。为了实现代码重用,Matlab提供了一种Mex文件(在Windows操作系统中为Dll文件)技术,可以在不改变现有代码的情况下,使用尽量少的时间和精力把C代码导入到Matlab中,可以象使用Matlab的内部函数一样使用它,从而解决了如何把现有的C代码在Matlab 中加以利用的问题,即如何把C代码导入到Matlab 中,而且这种Mex文件的执行效率比Matlab中的m文件要高,其详细内容在1.2节中讨论。

作为解决问题的途径之一,利用Matlab提供的工具mcc或其提供的一个插件(Add-in)程序,可以把非脚本m文件翻译成C/C++文件,然后将其嵌入VC工程中编译生成二进制代码,从而大大提高运行速度,而且还可以在VC中进行调试。在1.3节中将详细叙述Matlab与C++的接口及其应用问题。当然,Matlab还提供了其它一些技术,如Mat文件、计算引擎等,这些本文不讨论。

1.2 C语言的Mex文件接口及应用

首先看一个最简单的例子:

#include“mex.h”/*必须包含的头文件*/

void Mul(double*x,double*y,double*z)

{

*z=(*x)*(*y);

}/*函数的功能是实现两个数的相乘*/

void mexFunction(int nlhs,mxArray*plhs[], int nrhs,const mxArray*prhs[])

{

 double*x,*y,*z;

 int row0,col0;

 int row1,col1;

 /*检查输入输出变量的个数*/

 if(nrhs!=2)

(“.”);

 else

if(nlhs>1)

mexErrMsgTxt(“too many output arguments.”);

 /*输入的元素必须为两个非复数的double 类型数据*/

 row0=mxGetM(prhs[0]);

 col0=mxGetN(prhs[0]);

 if(!mxIsDouble(prhs[0])??mxIsComplex (prhs[0])??

!(row0==1&&col0==1))

mexErrMsgTxt(“inputs must be nocomplex scalar double.”);

 row1=mxGetM(prhs[1]);

 col1=mxGetN(prhs[1]);

 if(!mxIsDouble(prhs[1])??mxIsComplex (prhs[1])??

!(row1==1&&col1==1))

mexErrMsgTxt(“inputs must be nocomplex scalar double.”);

 /*为返回参数创建矩阵*/

 plhs[0]=mxCreateDoubleMatrix(row0, col0,mxREAL);

 /*为输入输出参数赋值*/

 x=mxGetPr(prhs[0]);

 y=mxGetPr(prhs[1]);

 z=mxGetPr(plhs[0]);

 /*调用C函数Mul*/

 Mul(x,y,z);

}

这个例子实现的是两个数的相乘,各个语句的含义请参见注释;以mx,mex开头的函数是Matlab 与C的接口函数,具体用法请参见Matlab的帮助。该例子的源程序主要由两个不同的部分组成:

1)计算子程序。它包含了所有实际完成计算功能的源代码,用来完成实际的计算工作;

2)入口子程序。它是计算子例行程序同Matlab 环境之间的接口,用来完成两者之间的通信任务。入口子例行程序的名称为mexFunction,拥有四个参数,分别为prhs、nrhs、plhs和nlhs,其中prhs为一个mxArray结构体类型的指针数组,该数组的数组元素按顺序指向所有的输入参数;nrhs为整数类型,它标明了输入参数的个数;plhs同样为一个结构体类型的指针数组,该数组的数组元

41

第4期 周正人等: M atlab与C/C++的接口及其在仿真中的应用

素按顺序指向所有的输出参数;nlhs 为整数类型,它标明了输出参数的个数。

以上两个步骤是典型的C 语言Mex 文件格式。其执行流程如图1所示。为了能够在Matlab 环境下运行这个程序,必须首先配置Mex 的编译环境,其配置工作可在Matlab 环境中运行mex-setup 命令

并按提示进行操作。配置之后,在Matlab 环境下运

行mex filename.c 编译C 文件,然后可在当前目录

下看到一个与C 文件同名的dll 文件,到此为止已

经大功告成。在Matlab 环境下键入filename (2,3)看看结果,

检验一下是否正确。

以上是个非常简单的例子。在C 语言编程中经常用到结构,下面是一个与数据结构有关的例子。

#include “mex.h ”

struct Point {

 double x; double y ; double z;};

void Add(struct Point *p){

 p->x ++; p->y ++; p ->z ++;}

void mexFunction (int nlhs ,mxArray *plhs [],int nrhs,const mxArray *prhs[])

{

 const char *fnames[3]; int nfields ,n ,i ; mxArray *tmp; struct Point p1; double *x [3]; if(nrhs !=1)

(“

.”);

 else if(nlhs >1)

mexErrMsgTxt (“too

many

output

argument.”);

 else if(!mxIsStruct(prhs[0]))

mexErrMsgTxt (“input must be a structure.”);

 /*求得输入结构体的域数和每个域的元素个数*/

 nfields =mxGetNumberOfFields (prhs [0]); n=mxGetNumberOfElements(prhs[0]);

 for(i=0;i

fnames [i]=mxGetFieldNameByNumber (prhs [0],i );

 for(i=0;i

 {

tmp =mxGetField (prhs [0],0,fnames [i]);

if (mxIsDouble (tmp )!=1) mexErrMsgTxt(“Element is not type of double.”);

x [i ]=mxGetPr (tmp ); }

 1.=*([0]);

42

电光与控制 第9卷

 p1.y=*(x[1]);

 p1.z=*(x[2]);

 Add(&p1);

 /*对输出的结构体矩阵进行初始化并赋值*/

 plhs[0]=mxCreateStructMatrix(1,1, nfields,fnames);

 tmp=mxCreateScalarDouble(p1.x);

 mxSetField(plhs[0],0,fnames[0],tmp);

 tmp=mxCreateScalarDouble(p1.y);

 mxSetField(plhs[0],0,fnames[1],tmp);

 tmp=mxCreateScalarDouble(p1.z);

 mxSetField(plhs[0],0,fnames[2],tmp);

}

这个例子同第一个的格式是一样的,区别在于一些mx函数的使用上。对于Matlab中的结构类型,其实质还是数组。因此,不一定非要使用上面的实现方式,上面的实现方式是考虑到Matlab的结构类型和C语言中的结构形式相对应。

上面举的两个例子都是单个文件的,如果C函数用到多个文件中的函数,编译时的格式如下:mex file1.c file2.c…,编译后将产生file1.dll的动态链接库文件,可在Matlab工作环境中直接执行。注意: mex命令可以操作多种文件格式,包括.c、.obj和. lib;在链接多个文件时,生成的Mex文件的名字为文件列表中的第一个文件的名字;在将文件列表时,必须写出文件扩展名,并且用空格分开。

1.3 Matlab与C/C++的接口及应用

也许Math Works公司的意思是利用mcc命令将m文件编译生成stand-alone程序。因而没有过多考虑如何将mcc生成的C/C++文件嵌入到VC 工程中,但其新版提供了一个与VC集成得比较好的插件(Add-in)程序可以将m文件翻译成C/C+ +文件,并且可以把VC工程选项自动配置好。下面将详细介绍使用mcc和插件(Add-in)程序将m文件翻译成C/C++文件嵌入到VC工程中的方法。

1.3.1 使用mcc

把mcc产生的C++文件嵌入到VC工程中时,VC工程的配置如下:

新建一个项目或者打开一个已有项目,然后选择菜单:

Project->Settings

:

C/C++选项页:

Category:General

Preprocessor definitions:增加MSVC,IBMPC, MSWIND

Category:Code Generation

U se run-time library:Multithreaded DLL

Link选项页:

Category:Input

Object/Library modules:增加libmatlb.lib libmx.lib libmat.lib

 d:\Matlab6p1\extern\lib\win32\libmatpm. lib

Additional Library path:d:\Matlab6p1\extern\ lib\win32\microsoft\msvc60

T ools->Options->Directories

Platform:Win32

Show directories for:Include files

Directories:增加d:\Matlab6p1\extern\include,

 d:\Matlab6p1\extern\include\cpp

以上需要增加的库函数不需要用其它工具生成,Math Works公司已经做好,随Matlab一起安装在目录d:\Matlab6p1\extern\lib\win32及子目录下。完成以上的配置工作后,就可以利用mcc命令把m文件翻译成C++文件嵌入到VC工程中去, mcc的命令格式为:

mcc-t-L Cpp filename.m 请注意大小写。

这时不仅可以把mcc命令生成的C++文件嵌入到VC工程中进行编译,还可以直接在VC中包含一些必要的头文件(位于d:\Matlab6p1\extern\ include\cpp)后使用matlab的矩阵函数。

下面举一个简单的例子。test.m实现的是两个矩阵的加和减:

function[a,b]=test(x,y)

a=x+y;

b=x-y;

利用mcc-t-L Cpp test.m命令生成test.hpp和test.cpp文件。头文件test.hpp的内容如下:

//

//MATLAB Compiler: 2.2

//Date:Tue Jan1508:17:192002

//Arguments:“-B”“macro default”“-O”“all”“-O”“fold scalar mxarrays:on”

//“-O”“fold non scalar mxarrays:on”“-O”“optimize integer for loops:on”“-O”

43

第4期 周正人等: M atlab与C/C++的接口及其在仿真中的应用

//“array indexing:on”“-O”“optimize conditionals:on”“-t”“-L”“Cpp”“test.m”

//

#ifndef test hpp

#define test hpp1

#include“libmatlb.hpp”

extern void InitializeModule test();

extern void TerminateModule test();

extern mexLocalFunctionTable local function table test;

extern mwArray test(mwArray*b,

mwArray x=mwArray::DIN,

mwArray y=mwArray::DIN);

#ifdef cplusplus

extern“C”

#endif

void mlxTest(int nlhs,mxArray*plhs[],int nrhs,mxArray*prhs[]);

#endif

在VC中调用test函数的主程序文件如下:

#include

#include“test.hpp”

void main()

{

 double data[]={1,3,2,4};

 mwArray a(2,2,data),b(2,2,data),c,d;

 c=test(&d,a,b);

 cout<

 cout<

 cout<

}

从上面可看出,这时还可以直接调用Matlab的矩阵计算函数,如求逆inv、求行列式det。

1.3.2 使用插件(Add-in)

上面的方法也许显得有点复杂,不仅要增加预处理宏,还要加入必要的库文件。Math Works公司也许正是考虑到了这一点,因此提供了另外一个工具,作为VC的一个插件(Add-in)。这个工具与VC 结合得非常不错,使用前最好是在Matlab环境下使用命令mbuild-setup进行配置。配置后,在VC中选择菜单T ools->Customize…->Add-in and Macro files,在Add-in macro下选中Matlab Add-in。返回VC开发环境后就可看到一个名字为T oolbar1的浮动工具栏,在新建工程选项中将增加一个MATLAB Project Wizard项目。在使用时,可以有两种途径:

1)如果已经建立了工程文件,用鼠标直接点击T oolbar1上的.m下面带有++号的图标,弹出一个对话框,第一项选择Windows Console EXE,选中下面的复选框Generate C++、Debug mode(也可以根据自己的需要选择选项)。点击OK按钮,然后在其提示下,一步一步往下操作,就可以了。

2)若还没有建立工程文件,可以在新建工程选项中选择MATLAB Project Wizard来建立工程,输入工程名称后,点击OK按钮,弹出一个对话框,其选项的意思大概为:应用程序类型,是否产生主函数文件,是否使用图形句柄,应用程序的语言是用C 还是C++,选用Debug模式还是Release模式。这些需要根据实际情况选择。选择完成后,点击Finish 按钮,按其提示一步一步往下操作,就可完成了。

这种方法比mcc要简单很多,VC的工程选项不必自己去配置,它已经把一切都配置好了。当然,头文件的路径还得自己动手。这样可以在VC环境下,对程序进行调试,生成独立于Matlab的程序。注意:以上两种方法生成的程序在运行时,都必须带上一些Matlab提供的动态链接库(Dll文件)。

2 结论

Matlab提供的外部接口,可以把现有的C/C+ +代码不做修改而只需增加入口函数,就能导入Matlab中使用,因而可以在利用现有代码的同时,使用Matlab的强大功能进行火控系统仿真软件的开发,并且可以提高开发效率、节省时间和精力。

使用mcc或Matlab提供的一个外挂程序,可以把Matlab的m文件翻译成C/C++文件嵌入到VC工程中进行编译和调试,从而把两者的优势都充分发挥出来,快速而高效地开发火控仿真软件。

参考文献:

[1] Math Works.Matlab C/C++Math Librar y version

2.12001.

[2] 薛定宇.科学运算语言MAT LAB5.3程序设计与应

用[M].北京:清华大学出版社,2000.

44 电光与控制 第9卷

相关主题
文本预览
相关文档 最新文档