posts - 0,  comments - 0,  trackbacks - 0

注意:旨在提供一份 VC++调用 Matlab的快速试验参考和一些实际经验,不保证所有内容都完全正确,一些叙述(特别是关于 COM)也不太规范,欢迎大家批评指正。

本文讨论使用 Matlab COM Builder从.m文件生成 COM 组件,并在 MFC应用程序中调用的基本步骤,程序的发布,以及一些注意事项。

开发环境
Windows XP Pro SP3
VC++ 6.0 SP6
Matlab 6.5

步骤
1)检查 VC++相关环境变量
安装 VC++ 6.0 的过程中,有一个“register environment variable”选项。如果你已经
勾选了这一项,可以跳过本步骤;如果没有,请按照 C:\Program Files\Microsoft Visual
Studio\VC98\Bin\VCVARS32.BAT设置环境变量。
2)为 VC++的 include 和 lib 文件查找目录添加 Matlab 项目:

3)设置 Matlab 与 VC++编译器关联
打开 Matlab,执行带“–setup”选项的 mbuild 和 mex,选择 VC++ 6.0 Compiler 作为默认的编译器。

4)编写.m文件,使用 Matlab COM Builder 生成 COM 组件作为简单的演示,新建 D:\MATLAB6p5\work\test.m,内容如下:

function test()
x = -10:0.1:10;
y = sin(x);
figure('visible','off');%
set(gcf,'menubar','none');
plot(x,y);
figure(1);%

调用 test()将显示 sin 在[-10,10]区间的曲线:

以%结束的语句是为了消除闪烁,这个在最后在 VC中调用时还是看得出效果的,可以再验证一下。

在 Matlab命令提示符下输入 comtool打开 Matlab COM Builder,新建工程ComTest,设置右图所示:

在“Compiler options”中,第一项是必需的,因为我们使用了图形相关的函数,后面的两项无所谓。点击“OK”,然后将前面编写的 test.m添加到工程中,点击“Build“进行编译。

5)使用 OleView.exe 生成 COM 组件的接口定义文件
如果一切顺利的话(但愿如此☺),会在工程目录下生成很多文件。不过,只有D:\MATLAB6p5\work\ComTest\distrib\ComTest_1_0.dll 才是我们唯一需要关心的。从“开始”->“Microsoft Visual C++ 6.0”->“Microsoft Visual C++ 6.0 Tools”找到“OLE View”,点击打开以后从左侧的“Type Libraries”下找到“ComTest 1.0 Type Library”,双击打开此节点后分别保存为.h 和.c文件。有了 ComTest_1_0.dll,ComTest_1_0.h 和 ComTest_1_0.c,我们就可以在 VC中使用 ComTest组件了。注意这一步能否成功和步骤 1)和 2)有很大关系,所以如果出错,很可能是因为它们没有被正确配置。

6)在 MFC应用程序中调用 COM 组件
请看代码:

// ComBuilderTestDlg.cpp : implementation file
#include "stdafx.h"
#include "ComBuilderTest.h"
#include "ComBuilderTestDlg.h"

#import "mwcomutil.dll"
#import "Matlab/ComTest_1_0.dll"

#include <mwcomutil.h>
#include "Matlab/ComTest_1_0.h"

void CComBuilderTestDlg::OnBtnComTest()
{
IPlotSin *pInst;

if (FAILED(::CoInitialize(NULL)))
{
   AfxMessageBox("CoInitialize Failed");
   return;
}

HRESULT hr = ::CoCreateInstance(CLSID_PlotSin, NULL, CLSCTX_ALL,
   IID_IPlotSin, (void**)&pInst);
if (SUCCEEDED(hr))
{
   hr = pInst->test();
   pInst->Release(); // 不需要pInst了
}
else
{
   AfxMessageBox("CoCreateInstance Failed");
   return;
}

// 窗口嵌入
HWND hFigure = ::FindWindow(NULL, "Figure No. 1");
if (hFigure)
{
   m_pWndFigure = CWnd::FromHandle(hFigure);
   ASSERT(m_pWndFigure);

   m_pWndFigure->SetParent(this);
   m_pWndFigure->ModifyStyle(WS_CAPTION | WS_BORDER, WS_MAXIMIZE, 0);
  
   CRect rt;
   GetClientRect(&rt);
   m_pWndFigure->MoveWindow(0, 0, rt.Width(), rt.Height(), TRUE);
   m_pWndFigure->SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}

::CoUninitialize();//一定要调用这个,否则图像出不来。。。
}


void CComBuilderTestDlg::OnClose()
{
// 退出前关闭figure窗口,否则进程无法结束
if (m_pWndFigure)
{
   ::PostMessage(m_pWndFigure->GetSafeHwnd(), WM_CLOSE, 0, 0);
   ::CoUninitialize();
}

CDialog::OnClose();
}

使用了::FindWindow、CWnd::SetParent等将 ComTest组件创建的 figure窗口嵌入到程序窗体中,虽然不是很完美(如果你有更好的方法,谢谢通知我)。注意在程序结束前要关闭 figure 窗口,否则将导致进程无法结束。程序截图如下:

注意事项
再次声明一下,VC相关的环境变量设置很重要,我是在这上面栽了跟头的/。另外,(在这个例子中)一定要记得调用::CoUnInitialize,否则 sin 图像出不来。如果你知道为什么,谢谢通知我。

发布
几乎也是傻瓜式的。comtool中有个“package component”命令,执行可以得到一个自解压文件,在客户计算机执行并按照提示操作就可以了。

转自:http://www.cnitblog.com/buf

阅读全文
类别:visual c++ 查看评论
posted on 2010-10-14 16:57 ewook 阅读(337) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理