Matlab 版 (精华区)

发信人: bage (醍醐灌顶@洗心革面), 信区: Matlab
标  题: C++Builder与Matlab混合编程的实现
发信站: 哈工大紫丁香 (2001年04月13日11:08:35 星期五), 站内信件

                     C++Builder与Matlab混合编程的实现
                                长沙 张云洲

  在C++Builder中调用Matlab工具箱函数,有两种实现方式。一种是基于Matlab环境
支持,通过必要的设置实现;笔者在本刊上曾撰文对这种方式进行了专门的阐述。另一
种则是完全脱离Matlab环境,通过动态连接库方式实现对Matlab工具箱函数的调用,这
可以通过一种开发平台Mediva来实现。相对来说,前者的限制因素较多,而后者则较为
方便灵活。
一、Mediva软件平台
  Mediva是Mathtools公司推出的一种Matlab编译开发软件平台,提供对Matlab程序文
件(M文件)的解释执行和开发环境支持。该软件有为Borland C++、Visual Basic和De
phi等编程语言开发的不同版本,目前其版本已经到了4.5版。软件大小仅6.5M,可以通
过访问其站点www.mathtools.com免费下载试用一个月。 Mediva软件平台本身的功能相
当强大,提供近千个Matlab的基本功能函数,通过必要的设置,就可以直接实现与C++的
混合编程,而不必再依赖Matlab;同时,Mediva还提供编译转换功能,能够将Matlab函
数或编写的Matlab程序转换为C++形式的DLL,从而实现脱离Matlab环境对Matlab函数和
过程的有效调用,这样就有可能实现对Matlab强大的工具箱函数的利用。
  Mediva的缺点是C++与Matlab混合编写的应用软件必须携带必要的DLL,从而增大了
软件的体积(约4M),同时也不能对所有的Matlab函数提供支持,例如采用类库进行设
计的部分函数。但尽管如此,对于控制系统计算机设计、分析的工作来说,Mediva仍不
失为一个好的工具。
  由于利用Mediva将Matlab工具箱函数转换成DLL的内容较多,限于篇幅本文在此仅给
出对Matlab函数直接调用的实现,而将另撰文阐述DLL的实现。
二、C++Builder直接调用Matlab函数
  本文假设已经安装了Mediva软件或已经得到必要的两个动态连接库mdv4300.dll和a
go4300.dll。
  Mediva提供的近千个Matlab基本功能函数,都可以在C++Builder中直接调用。这些
函数包括基本的操作、命令、I/O、线性代数、位图、控制等,基本上可以满足我们的一
般需要。当然其最大的优点就是可以直接在C++Buider中直接调用而不必考虑安装庞大的
Matlab。
  其实现方式和步骤如下:
  1.Lib文件的生成
  在Dos下用C++Builder中的Implib.exe,通过如下命令生成mdv4300.lib: implib m
dv4300.lib mdv4300.dll
  将上述两个DLL文件和此Lib文件拷贝到当前目录下。
  2.实现与Matlab的混合编程
  Matlab.h包含了Mediva中所有类型、常量、函数的说明和定义,必须将此头文件放
于程序的第一行。Mediva给出的Matlab函数形式并不特殊,如绘线函数Plot,在Mediva
中说明为:Mm DLLI plot(cMm varargin);varargin与Matlab 中的意义是一样的,与输
入变量的个数相对应。所有可以直接使用的函数都在Matlib.h头文件中定义,而在mdv4
300.dll中实现。
  但在C++Builder中使用Mediva提供的Matlab函数的格式,与Matlab编程稍有不同,
这主要体现在C++中必须进行必要的说明上。例如我们要用绘线函数Plot来绘制数组x[1
00]的红色图线。在Matlab中调用为Plot(x,'r');在C++中调用则为:Plot(CL(x),TM("
r")),其中CL是一个关键字,是多变量输入时所必须使用的,用以指明调用的变量;而
TM则指明,这是一个字符。
  下面我们给出一个示例程序,其功能是对一个1024点的输入数组进行FFT 变换,并
绘制变换后频谱实部的火柴杆图,最后将原数据和变换后的数据写入数据文件中。
#include "matlib.h"
//必须包含的头文件
#include < vcl.h >
#pragma hdrstop
#include "TryMatcomU.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    int k=0;
    initM(MATCOM_VERSION);    //必须进行的初始化
    Mm cur1,cur2;   //定义变量
    cur1=zeros(128);  cur2=zeros(128);  //变量初始化
    for  (k=1;k< =128;k++)
   cur1.r(k)=randM();    //生成一个随机数列
    figure(1);
    plot(cur1);//图形显示该数列
   cur2=fft(cur1,128);  //做128点fft变换
   figure(2);
   //绘制fft变换后实部的火柴杆图,注意此处多变量输入的格式
   stem((CL(cur1),real(cur2),TM("r")));
 fid=fopen(filename,mode,format) opens
   exitM();   //退出调用
}
  如果完全使用C++来实现本程序的工作,其代码将超过300行!由此可以看出,C++B
uilder与Matlab函数的混合编程可以给我们带来多么大的方便!
  3.变量内部状态/数据的观察方法
  Mediva使用的所有变量均定义为Mm类型。如果在C++Builder中观察Mm类型变量的内
部状态/数据,要稍麻烦一些。但在调试程序时,这又是不可避免的一步,这里举例给出
变量观察的方法。
  例如对上面生成的cur2数列进行观察,
  *cur2.pr 0.1892 cur2(1)的实部
  *cur2.pi 0.0013 cur2(1)的虚部
三、C++Builder调用Matlab工具箱函数转换后的DLL
  1.Matlab函数向DLL的转化
  Mediva软件提供了将Matlab函数转换为DLL的功能,非常方便。但需要注意的是:
  1.Matlab5.0以上版本,所有带有tf类的函数均无法转换;
  2.Matlab4.2以下版本,多数函数能够转换,但转换后大多不能直接使用,而必须加
以处理。
  MATCOM V4.3中把含有输入参数的M文件转换成DLL时,生成的DLL无法调用.以.M为例
,
  function [x1,x2]=flower(x3)
  MATCOM生成的FLOWER.CPP和FLOWER.H中声明为:
Mm flower(Mm x3, i_o_t, Mm& x1__o, Mm& x2__o) {
begin_scope
x3.setname("x3");
...
    }
Mm flower(Mm x3);
Mm flower(Mm x3, i_o_t, Mm& x1__o, Mm& x2__o);
而生成的G_FLOWER.CPP声明为:
---- void DLLX _stdcall flower_1_1(Mm** in01, Mm **out01)
---- void DLLX _stdcall flower_1_2(Mm** in01, Mm **out01, Mm **out02)
---- 其中对于in01的说明是不正确的.应按如下修改。然后,按如下MAKE文件进行编译

#
# MATCOM makefile
#
all: flower.dll
g_flower.obj: g_flower.cpp
 bcc32 -c -Id:\matcom43\ -WD -Id:
 \matcom43\lib -H=matlib.csm -a4
 -5 -eg_flower.obj g_flower.cpp
flower.dll: flower.obj g_flower.obj
 bcc32 -Ld:\matcom43\ -WD -Id:
 \matcom43\lib -H=matlib.csm -a4 -5 -eflower.dll
 @flower.rsp d:\matcom43\lib\mdv4300b.lib
  在CPP中调用这个函数之前,一定要先给in01分配空间。
  #include "matlib.h"
  #pragma hdrstop
  #include "flower.h"
  #define WIN32_LEAN_AND_MEAN
  #include < windows.h >
  #include "matlib.h"
  #pragma hdrstop
  extern "C" {
    void DLLX _stdcall flower_1_1(Mm in01, Mm **out01) {
 *out01=new Mm();
 //*in01=new Mm();
 **out01=flower(in01);
 exitM();
    }
    void DLLX _stdcall flower_1_2(Mm in01, Mm **out01, Mm **out02) {
 *out01=new Mm(); *out02=new Mm();
 //*in01=new Mm();
 flower(in01, i_o , **out01, **out02);
 exitM();
    }

--
                     
           ooooO    Ooooo      *********************************
           (    )   (    )     #    大肚能容,容天下难容之事    #  
            \  (     )  /      #    开口便笑,笑世间可笑之人    #
             \  )   (  /       *********************************
              ~~     ~~

※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: bage.hit.edu.cn]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:4.246毫秒