一组MATLAB和 C++数据交换类的设计

来源:互联网 发布:十大网络写手 编辑:程序博客网 时间:2024/06/14 02:05

 一组MATLAB和 C++数据交换类的设计
 

南京航空航天大学 san  email visualsan@yahoo.cn

 

总体结构图

总体结构图

本文将针对如何进行 MATLAB C++ 交互进行探讨,编程环境问为 matlab2009 VC6.0 。具体如何设置编程环境请参考 help 。内容总体分三部分: 1.matlab 引擎调用类封装。 2. 数据接口类设计,包括 mat 类型文件操作类设计。 3. 具体举几个实例。所有源代码包括例子,在我的空间中可以找到,有参考需要的朋友可以关注一下。

MATLAB 引擎总体结构分成两部分:数据交换和后台计算服务,由 matlab 命令控制。数据交换接口负责数据输入和数据输出。数据输入将计算说需要的变量导入到计算引擎中;数据输出接口则将计算结果提取出来进一步处理,典型的matlab应用是首先向matlab 传递参数、然后进行复杂的运算,最后提取感兴趣的结果。利用matlab 强大的计算能力以及C++的灵活性可发挥各种功能的极限,从而提高工作效率。关于matlab 和c++的相互调用的文章很多,但是在两者之间进行数据传递是一个比较麻烦的事情,要求程序员对MATLAB 的C API相当熟悉,所以非常不便。我接触MATLAB 和C++有几年了,相关书籍和文件教程让我受益匪浅,闲暇之余就总结了一下自己所学的知识,用面向对象方法开发了matlab和c++交互的类,写出来探讨一下。

 

计算引擎分为全局引擎和局部引擎。全局引擎只有一个,一旦启动全局引擎,则所有的计算结果和变量都是全局共享的。局部引擎是独立于线程的一个计算引擎,它的数据是局部拥有的,可以启动任意多的局部引擎,取决于计算机配置。启动一个局部引擎相当于开启一个独立的 MATLAB 线程,由于启动 MATLAB 是一个很耗时间的过程,因此应该尽量减少局部引擎的启动数量。引擎控制有类 CMatlabEngine 控制。 CMatlabEngine 的结构如下:

CMatlabEngine类结构图

bSingleUse=1 表示启动局部引擎, bSingleUse=0 表示启动全局引擎,全局引擎在第一次调用时打开 MATLAB ,以后每调用一次 OpenEngine 打开全局 MATLAB ,则引用计数加一;调用一次 closeEngine 引用计数减一。当引用计数为 0 时,表示当前没有程序对全局 MATLAB 进行调用,此时将自动关闭 MATLAB

调用 void SetEngineVisible(BOOL bVisible) 将决定是否显示 MATLAB 的窗口界面。函数 void PutVar(char *name,MatlabData* d) 将向 MATLAB 空间中添加一个自定义变量,其中 name 为变量名称, d 为变量内容,若该变量已经存在,则调用该函数将覆盖已存在变量值。函数 BOOL GetVar(char *name,MatlabData** d) 将从 MATLAB 空间中提取一个变量,其中 name 为变量名称, d 为输出指向内容指针的指针,若该变量不存在,则返回 FALSE

void EvalString(char* matlabString) 可以和计算引擎进行命令交互, matlabString 为命令,和常规使用 MATLAB 软件所进行的输入一致。一旦调用某个命令, MATLAB 将有反馈输出,可能是计算结果,也可能是错误信息,这些信息可以通过调用 const char* GetOutPut() 来获取。

 

2. 数据类型接口设计

   所有 MATLAB的 C API的数据类型是 mxArray MATLAB 提供了一组 C  API 来进行数据操作。 mxArray 是一种包含多种类型的数据,可以是数值,字符, cell 或者是结构体;数据类型可以是标量,矩阵,STRUCT或者是 Array

mxArray数据类型

针对实际应用,将常用的数据类型进行接口设计。数据结构可分为标量,矩阵和阵列。数据类型有双精度浮点数,单精度浮点数, 32 位整数, 64 位整数,字符串,布尔型。

 

如图所示,将数据结构分为三种,分别是:标量、矩阵和阵列。将数据类型分位四种:

浮点数、布尔型,整形和字符串。类继承关系图如下

ImxArray及其子类类继承关系图

 

ImxAray 为借口类,派生出矩阵 xMatrix<T> 和阵列 xAray<T> ,其中 T 位具体类型,采用模板技术,再将类型 T 具体化位实际数据类型如 int,double 等,可以得到相应的矩阵类和阵列类如 xMatrixDouble xMatrixInt 等。图中并为列出所有模板绑定的类型,更具体的类列表如下:

// 矩阵


 

 

 

 

 

 

最后开发包装接口mxWrap mxWrap 的构造函数提供了从标量、矩阵、阵列到字符的封装。根据不同的数据类型动态创建数据类型,从而实现了用

单一接口类来操作不同数据类型。下面将逐一介绍每个类的实现情况。

1.       ImxArray

ImxAray类结构图

ImxArray 是数据接口类,主要成员数据有三个:

mxArray *m_pArray;

       int       m_dataType;

       char     m_szTypeName[64];

(其中 mxArray MATLAB C API 的主要数据类型,通过 MATLAB C API 可以实现数据交互。具体使用情况可以参考 MATLAB HELP 。)

m_pArray 是存放 MATLAB 数据的指针, m_pArray 可以存放 MATLAB 中所有的数据,包括标量、矩阵、 STRUCT CELL 等类型数据,通过 CLASSID 来标示数据类型,通过获取数据维数来标示是标量,矩阵还是阵列。可用的 CLASSID 列表如下:

 

 

virtual mxArray* GetArray(){ return m_pArray;}

virtual bool     SetArray(mxArray* pArray,bool bCopy=0){ return 1;};

GetArray SetArray 未设置数据和获取数据的接口。 SetArray 带一个参数 bCopy 标示是否拷贝一份输入参数 pArray ,当 bCopy=0 ImxAray 对象将指向 pArray 所标示的数据,此时不能调用 mxDestroyArray 销毁 pArray ,否则将出错;若 bCopy=1 ImxAray 对象将拥有一份独立的 pArray 的拷贝。 ImxAray 一般不单独使用,而是通过 mxWrap 来调用, mxWrap 定义了一系列含不同参数的构造函数来生成特定类型的数据,具体可参考 mxWrap 的实现部分。


2.xBool 布尔类型

XBool类结构图

3.xDouble_Float<T> 浮点型

xDouble_Float<T>类结构

浮点型数据分为实数和复数, IsComplex 可判断数据类型。构造函数如下:

xDouble_Float(T valReal=0.0,T valImg=0,bool bComplex=0);

通过 bComplex 设置数据是实数还是复数。数据操作函数如下:

  

4. xinterger<T> 整型

 xinterger<T>

5.string 字符串

xString

6.xMatrix<T> 矩阵

 

xMatrix<T>矩阵

模板实例化如下:

 

矩阵的主要参数是行和列, GetR() 获得行数; GetC() 获取列数。构造函数如下:

       xMatrix(mwSize m=1, mwSize n=1, T *valReal=0,T *valImg=0,mxComplexity flag=mxREAL);

这里需要注意几点:

1.       matlab c++ 的数据存储方式有差别, matlab 的矩阵是按列存储的,所有在数据交互是需注意数据的格式。当输入矩阵时,比如:

输入数据是

11 12 13

21 22 23

而在 matlab 中矩阵是这样的:

11 13 22

12 21 23

即先从输入数据顺序读入: 11,12,13,21,22,23 ,,然后按列放置

先放置第一列

11

12

第二列:

11 13

12 21

第三列:

11 13 22

12 21 23

result

可以调用 static void  C2Mat(T* c_input,int r,int c,T*m_outPut); 来把 C 格式转换为 matlab 格式。这样你所输入的矩阵将和 MATLAB 空间中的矩阵一致:


result

2. 只有 double float 拥有复数类型,所有对于其他矩阵,复数没有意义,所以在构造函数初始化时: xMatrix(mwSize m=1, mwSize n=1, T *valReal=0,T *valImg=0,mxComplexity flag=mxREAL) ,参数 valImg=0 flag=mxREAL

7. xArray<T> 阵列

xArray<T>阵列

 

 

 

 

 

 

所谓阵列就是指维数在二维以上的数据,

int  GetDimSize(); 获取维数

int  GetDim(int index ); 获取第几维的长度

int  GetDataSize(); 获取存放的总数据个数,即维数尺寸的乘积

矩阵时维数维二维的阵列,在数据类型设计中,原本是这样考虑的:先构建阵列维模板,然后通过将阵列的维数设置为两维,从而派生出矩阵类,矩阵类的所有操作都委托给二维阵列,将矩阵的行数和列数设置为 1 ,从而派生出标量类,操作委托给行数和列数为 1 的矩阵,由于这些类都是模板类,所有对模板进行实例化可以得到各种不同的类型。

后来参考了 MATLAB C API ,发现 API 里对不同的数据类型的都有各自的处理函数,通过阵列函数来操作矩阵或者标量或许有些大材小用,影响性能。阵列的数据存放和矩阵一样是按列来的,对于三维以上的阵列,数据的输入可能就比较复杂了,处理时可要细心。 MATLAB 提供了 API 来进行数据转换,可以参考 HELP.

通过调用 GetRealData 可获取实部数据,注意缓存区大小要够,即 buffersize>= GetDataSize().

调用 SetRealData 设置数据。虚部处理一样。

 

8.xStruct 结构体

xStruct结构体 

结构体由若干数据项组成,每个数据项包括名称和数据,和 C 语言的结构体是一样的, xStruct 可以增加数据相或者删除数据项 .

  

9.mxWrap

mxWrap 

mxWrap 主要有多个不同参数的构造函数,通过传递不同的参数可以构造出不同的数据类型出来,包括标量、矩阵、阵列和结构体。和 matlab 的交互过程可简化为:

写入变量、执行计算和提取结果。使用 mxWrap 来写入变量和提取结果客大大简化交互程序。

举例子如下:

       矩阵 A=[1 2 3;4 5 6; 7 8 9;]; B=[11 21 31;41 51 61; 71 81 91;]; 矩阵 C=A*B;

代码如下:

 

 

result

 

10.xFile

Mat 文件是 matlab 特有的数据存储文件类型,将变量存储于 mat 文件可以很方便进行数据交互。 MATLAB 提供了一组 API 进行 mat 文件操作,这些 API mat 开头,如 matOpen

xFile 封装类 mat 文件的操作。

xFile

调用 bool  Open(char *matFile,char* mode="u"); 打开一个 mat 文件, mode 为操作方式,可以为 mode="r" , "u" 读写 ,"w" ,"w4","wL","wz" 压缩模式。

mxWrap* GetArray(char*name,bool bCopy=1); 获取特定名称的变量

void    SetArray(char*name,mxWrap*pArray); 添加变量,若该变量已经存在,则会更新变量

int     GetVarCount();// 获得变量的个数

mxWrap* GetArray(int index,std::string*nameOut=NULL,bool bCopy=1);

遍历所有遍历:

for (int i=0;i<GetVarCount();i++)

{

       std::string name;

       mxWrap*ptr=GetArray(i,&name);

}

 

 

 

 

 

 

一个写mat文件的例子:

 

将得到的mat文件调入matlab查看:

 

 

 

下面举例如何使用该程序

例一:

输入任意y=f(x),求y对x的n阶导数,结果存放到字符串中取得,并计算原函数和n阶导数在x0处的值。

 

 

编译运行:

输入 y=x^2+x

        n=1

        x0=10

输出:

       dff=2*x+1

       val=110

       dfval=21

 

 

    例2:mat文件操作

这个例子将展示如何用xFile读取mat文件和写mat文件

A=[1 2 3;4 5 6;7 8 9];

B="南京航空航天大学 san visualsan@yahoo.cn";

C.name="san";C.address="NUAA";C.score=99.9;C.matrix=[12  22 32];

D=123.00

E=100;

将A,B,C,D,E写入d://result.mat

 

将result.mat调入matlab查看:

 

 

 

从d:/result.mat读取所有变量并显示

 

结果如下:

 

 

                                                                             SAN 2011.3.6   南京航空航天大学 CEPE 202

                                                                              EMAIL:visualsan@yahoo.cn

 

 

 

原创粉丝点击