转贴:matlab的combuilder系列-matlab下做com组件

看完了下文,把MATLAB帮助也全看了,简单的例子是可以的,但是复杂点程序就是无法在C#调用。

组件可以生成,但调用时出错。如我想做BP神经网络的组件,调用时老提示newff出错。

com builder是matlab6.5才有的,也是mathworks公司推荐使用于混合编程的,这些日子我

对他进行了全方位的摸索,感觉是爽呆了,下面我们一起来揭开它的神秘面纱,^_^。

此系列分为以下几块:

1.matlab下做com组件

2.vb,c#.net实现调用

3.vc实现调用

4.打包

5.优缺点评注

其中2,3部分可以选择一个看

matlab下做com组件

com是component object module的简称,它是一种通用的对象接口,任何语言只要按照

这种接口标准,就可以实现调用它。matlab6.5新推出来的combuilder就是把matlab下的程

序做成com组件,供其他语言调用。

我们先准备两个测试文件,并copy一个图片到c盘下,起名叫1.jpg(这些你都可以改

的,我这儿是为了程序方便):

第一个叫im_test.m如下:

function im_test %这个文件不带输入与输出

I=imread(\'c:\1.jpg\'); %因为以前带有imshow的程序用mcc编成dll后用不

%了,所以想试combuilder是否

imshow(I); %能支持这些函数

第二个叫split2rgb.m,就是前些日子Zosco发给我的那个程序,因为它用mcc编成dl

l后有问题,所以我在这儿继续将它进行测试,而且它也带有多个输入及输出参数,所以也

正好拿来测试

在matlab的workspace下打comtool,就打开了matlab com builder,点击file-new

project,新建一个工程,在component name里填上comtest,Class name里填上一个sglt

est(并将自动生成classes里的comtest remove掉),complie

code in选c或c++都无所谓,将Complier options里的Use Handle Graphics library的复

选框画上,点击ok就行了。然后点击project--Add files,将im_test.m和split2rgb.m添加

入工程,然后点Build-Com Object,就会在comtest\distrib\文件夹下生成一个comtest_

1_0.dll(它就是做好的com组件),Build时matlab已经自动将此dll在注册表中注册,为了下

面能用其他编译器调用,我们还需做一个准备工作,开一个dos窗口,进入<matlabroot>/

bin/win32目录下(matlabroot为你机器上matlab安装的路径),打regsvr32 mwcomutil.dll

,即对mwcomutil.dll进行注册(这个dll是matlab下作的任何com组件都要用到的dll),下面

我们在其他编译器下调用时就可以用了。

^_^,是不是觉得做起com组件来很简单呢,matlab下可以给com组件中的类添加成员

�事件、方法等,我这儿其实是给类sgltest添加了两个方法,怎么添加成员和方法可以参

看matlab的com builder的帮助。

附录:split2rgb.m的源代码

%%// 测试文件

function [m_nHeight,m_nWidth,mOrigR,mOrigG,mOrigB]=Split2RGB(FileName)

%%// 读入一个Jpg文件,

mOrigData=imread(FileName);

%mDestData=imresize(mOrigData,0.5);

imwrite(mOrigData,\'c:\2.jpg\');

%%// 用三个变量保存其R,G,B分量

mOrigR=mOrigData(:,:,1);

mOrigG=mOrigData(:,:,2);

mOrigB=mOrigData(:,:,3);

%%// 获得图象的高度,宽度

[m_nHeight,m_nWidth]=size(mOrigR);

figure(1);

set(gcf,\'MenuBar\',\'none\')

imshow(mOrigData);

title([\'Orginal Image:\',FileName],\'Color\',\'b\',\'FontSize\',14);

xlabel([\'Height: \',num2str(m_nHeight),\' Width :\',num2str(m_nWidth)],\'Color\'

,\'b\',\'FontSize\',12);

%%// 写param文件

paraFName=[FileName(1:length(FileName)-4),\'.param\'];

fw\');

fwrite(fid,m_nHeight,\'uint32\');

fwrite(fid,m_nWidth,\'uint32\');

fclose(fid);

%%// 写 R 分量文件

RFName=[FileName(1:length(FileName)-4),\'_R.rot\'];

fw\');

fwrite(fid,mOrigR,\'uint8\');

fclose(fid);

%%// 写 G 分量文件

GFName=[FileName(1:length(FileName)-4),\'_G.rot\'];

fw\');

fwrite(fid,mOrigG,\'uint8\');

fclose(fid);

%%// 写 B 分量文件

BFName=[FileName(1:length(FileName)-4),\'_B.rot\'];

fw\');

fwrite(fid,mOrigB,\'uint8\');

fclose(fid);

--

come on,baby!

※ 来源:·BBS 水木清华站 http://smth.org·[FROM: 202.113.39.83]

发信人: xxhn (小湖南), 信区: MathTools

标 题: matlab的combuilder系列-vb,c#.net调用

发信站: BBS 水木清华站 (Wed May 21 10:24:38 2003)

这一部分讲vb,c#.net下怎么实现调用上一部分我们生成的comtest_1_0.dll(matlab下做的

com组件),记得一定先要对mwcomutil.dll进行注册(怎么注册参看上一部分)

1.vb下实现调用

打开或新建一个vb工程,点project-Reference,在弹出来的窗口中找到comtest 1.0

Type Library,将前面的复选框选上,点击ok,此时便将此com组件添加到工程里面去了,

此时你可以用对象浏览器看到comtest下有个sgltest类,这个类里面有两个方法im_test,

split2rgb,还有个MWFlags成员(这个成员是自动生成的),vb下测试代码如下:

测试im_test方法的代码:

Dim st As sgltest

Set st = New sgltest

Call st.im_test

测试split2rgb方法的代码:

Dim st As sgltest

Set st = New sgltest

Dim h As Variant, w As Variant, r As Variant, g As Variant, b As Variant,

filename As Variant

filename = "c:\\1.jpg"

Call st.split2rgb(5, h, w, r, g, b, filename)

可见matlab下函数的输入输出参数在com组件里全是variant型的变量,测试大获成功,结

果就跟matlab下运行的一摸一样,爽

2.c#.net下实现调用

打开或新建一个c#项目(我采用的是vs.net编辑器),选中右边的解决方案资源管理器

中的引用,点鼠标右键,选添加引用,在弹出来的窗口中选com,然后也找到comtest_1_0

.dll,点选择,然后确定就可,此时此com组件也添加到工程里面去了,同样我们可以选择

对象浏览器来看comtest及下面的sgltest类,c#测试项目如下:

测试im_test方法的代码:

comtest.sgltestClass st=new comtest.sgltestClass();

st.im_test();

测试split2rgb方法的代码:

comtest.sgltestClass st=new comtest.sgltestClass();

object h=null,w=null,r=null,g=null,b=null;

object filename="c:\\1.jpg";

st.split2rgb(5,ref h,ref w,ref r,ref g,ref b,filename);

可见输入参数是ref object型的,而输出参数是object型的,测试同样大获成功,与matl

ab下运行的结果一摸一样,爽呆了。

--

come on,baby!

※ 修改:·xxhn 于 May 21 10:27:53 修改本文·[FROM: 202.113.39.83]

※ 来源:·BBS 水木清华站 http://smth.org·[FROM: 202.113.39.83]

发信人: xxhn (小湖南), 信区: MathTools

标 题: matlab的combuilder系列-vc下调用

发信站: BBS 水木清华站 (Wed May 21 10:25:17 2003)

这一部分讲vc下实现调用第一部分我们生成的comtest_1_0.dll,同样要记得先对mwcomut

il.dll进行注册(怎么注册参看第一部分),vb和.net下实现对com组件的调用很简单,而v

c下实现这一步我可是摸索了好几天(主要是vc用的不好)

1.先做一些准备工作,用ole viewer工具

开始--程序--Microsoft visual studio6.0--Microsoft visual studio6.0 Tools--

OLE viewer(这个工具也可以通过在vc下点Tools--OLE/COM Object Viewer来打开,在Ole

viewer工具里,在右边选择Type libraries,将他展开,找到comtest 1.0 Type Library

,选中它,点鼠标右键,选view,便又弹出一窗口,点工具栏上的save按钮,分别将他保

存为comtest_1_0.h,comtest_1_0.c(也可以存为comtest_1_0.Idl接口文件),我们就可以通

过这两个文件实现对comtest_1_0.dll调用

2.vc下调用

新建或打开一个vc工程,注意,此时不用对编译器进行任何设置(而用mcc生成的dll我

们么设置一大堆,我这儿只设置了Precomplied headers,选Automatic use of precomplied

headers,写上 stdafx.h),将comtest_1_0.h和comtest_1_0.c加入工程,并复制

一个comtest_1_0.dll到工程目录下,由于comtest_1_0.dll还要用到mwcomutil.dll,所

以将<matlabroot>/extern/include/下的mwcomutil.h和mwcomtypes.h也加入工程

(将这两个文件拷贝入工程路径下,如果设置了library path,可以不加)

此时可以通过classView看到多出了_IID、IMWUtil,Isgltest类,Isgltest就是我们在mat

lab下建起来的sgltest类

vc下代码如下

//这几个是引入dll和头文件

#import "mwcomutil.dll"

#import "comtest_1_0.DLL"

#include "mwcomutil.h"

#include "comtest_1_0.h"

#include "comutil.h" //此文件是用来处理由char *向VARIANT类型的转换

测试im_test方法的代码:

if(FAILED(CoInitialize(NULL))) //初始化调用com

{

AfxMessageBox("unable to initialize COM");

}

Isgltest *st=NULL;

//创建一个com组件,CLSID_sgltest和IID_Isgltest可以从comtest_1_0.h和comtest_

1_0.c里找到

HRESULT hr=CoCreateInstance(CLSID_sgltest,NULL,CLSCTX_ALL,IID_Isgltest,(voi

d **)&st);

if(SUCCEEDED(hr))

{

st->im_test();

AfxMessageBox("succeed");

st->Release();

}

else

{

AfxMessageBox("unsucceed");

}

如果你的vc工程是console project的话,上述的AfxMessageBox可改成printf或cout,

测试split2rgb方法的代码(类型转换我参照visual c的精华区也转换成功了)

if(FAILED(CoInitialize(NULL)))

{

AfxMessageBox("unable to initialize COM");

}

Isgltest *st=NULL;

HRESULT hr=CoCreateInstance(CLSID_sgltest,NULL,CLSCTX_ALL,IID_Isgltest,(voi

d **)&st);

VARIANT m,n,r,g,b,filename;

VariantInit(&m);

VariantInit(&n);

VariantInit(&r);

VariantInit(&g);

VariantInit(&b);

VariantInit(&filename);

filename.vt=VT_BSTR;

filename.bstrVal=_com_util::ConvertStringToBSTR("C:\\1.jpg");

if(SUCCEEDED(hr))

{

st->split2rgb(5,&m,&n,&r,&g,&b,filename);

st->Release();

AfxMessageBox("succeed");

}

else

{

AfxMessageBox("unsucceed");

}

同样,运行结果与matlab下的结果一摸一样,记得我们的im_test里面可是使用了imshow阿

,以前用mcc生成的程序中用它可是有错哦,爽呆了。

关于VC下用com组件及其类型的转变请参看msdn及其Visual C的精华区

--

come on,baby!

※ 修改:·xxhn 于 May 21 10:36:09 修改本文·[FROM: 202.113.39.83]

※ 修改:·xxhn 于 May 21 20:23:21 修改本文·[FROM: 202.113.39.83]

※ 修改:·xxhn 于 May 23 19:12:04 修改本文·[FROM: 202.113.39.16]

※ 来源:·BBS 水木清华站 http://smth.org·[FROM: 202.113.39.83]

发信人: xxhn (小湖南), 信区: MathTools

标 题: matlab的combuilder系列-打包及其优缺点评注

发信站: BBS 水木清华站 (Wed May 21 10:25:42 2003)

^_^,combuilder系列可以结尾了

一.打包:

在matlab下的workspace里打comtool,点file-open project将我们先前建好的comte

st.cbl工程文件打开,再点component--package component就实现了打包,此时到

comtest\distrib文件夹里看,生成的comtest.exe就是打包后

的解压程序,双击它会解压出一些文件,再点击解压出来的_install.bat就可以实现安装

(按他的步骤去做就行了)

二.优缺点评注

这几天用这个combuilder可把我给爽死了,特别是在vc下调用成功时,记得精华区里

曾讲combuilder没有什么实质性的突破,我可不这么认为,它的突破可大了

1.做出来的是com,通用的,任何编译器只要支持com,就可以实现调用,想c++ build

er,Delphi等的,我想只要按照调用com组件去做,也能成功的

2.支持imshow等一些原来混编用不了的函数,对图形库的支持也比以前强(这些还需各

位大侠共同测试)

3.实现方法简单,没有像以前混编还要设置一大堆东东

4.能够在matlab下写自己的类,并为自己的类编写成员、方法和事件,管理工程也方

便(这个有点像vc、vb下管理工程一样)

用的太爽了,一下子还不知道怎么写缺点了,^0^,我想缺点还需大家一起用来找出

我这儿说一个缺点,感觉它的参数全是VARIANT型的,不怎么方便

--

come on,baby!

※ 修改:·xxhn 于 May 21 10:29:04 修改本文·[FROM: 202.113.39.83]

※ 来源:·BBS 水木清华站 http://smth.org·[FROM: 202.113.39.83]

发信人: capriccio (俊), 信区: MathTools

标 题: vc中的数组和com中的VARIANT变量的相互转换

发信站: BBS 水木清华站 (Thu May 29 23:22:28 2003), 转信

用一个例子说明一下,

首先用matlab的m文件描述一下例子中com组件的功能:

function y=hehe(x)

y=x*2;

把该文件保存为hehe.m

用combuilder中建立工程comparatest,加入类paratest,

然后加入文件hehe.m,再build成为com组件。

下面是vc中的代码:

#include "stdafx.h"

#include "stdio.h"

#import "mwcomutil.dll"

#import "comtest2_1_0.DLL"

#include "mwcomutil.h"

#include "comtest2_1_0.h"

#include "comutil.h"

int main(int argc, char* argv[])

{

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

int i=4;

if(FAILED(CoInitialize(NULL))) //初始化调用com

{

printf("unable to initialize COM");

}

VARIANT x,y;

VariantInit(&x);

VariantInit(&y);

x.vt=VT_R8|VT_ARRAY;//声明x的类型为VT_ARRAY,

//Array中的元素为double型

SAFEARRAYBOUND rgsabound[1];

rgsabound[0].cElements=4;//元素的个数

rgsabound[0].lLbound=0; //矩阵索引的下界

x.parray=SafeArrayCreate(VT_R8,1,rgsabound);//该函数新建

//一个SafeArray,并把这个SafeArray的描述

//符的指针传给x.parray。

x.parray->pvData=a;

Iparatest *st=NULL;

//创建一个com组件,CLSID_paratest和IID_Iparatest可以从

//comparatest2_1_0.h和comparatest2_1_0.c里找到

HRESULT hr=CoCreateInstance(CLSID_paratest,NULL,CLSCTX_ALL,

IID_Iparatest,(void **)&st);

if(SUCCEEDED(hr))

{

st->hehe(1,&y,x);

memcpy(a,y.parray->pvData,4*sizeof(double));

//当matlab文件中返回的矩阵y是实数行的时候,com组件

//把得到的y的值存放再y.parray->pvData所指向的内存区域。

printf("%f\n%f\n%f\n%f\n",a[0],a[1],a[2],a[3]);

printf("succeed");

st->Release();

}

else

{

printf("unsucceed");

}

return 0;

}

上面的方法解决了实矩阵参数在com组件和vc之间的传递,应该也能用到其他

类型的矩阵,比如字符和整型的矩阵。但是如果com组件是由matlab combuilder

编译m文件得到的,而且m文件所返回的矩阵是复数型的,就不行了。因为好像

这时返回的矩阵并不是如上所述保存在y.parray中,至于到底保存在什么地方

就有待于大牛们把它找出来了,反正俺琢磨了一整天也没有一点头绪:(

--

※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.33.68]

发信人: xxhn (小湖南), 信区: MathTools

标 题: Re: Matlab与VC混合编程中出现的问题(用idl或dll来调用)

发信站: BBS 水木清华站 (Tue Aug 19 15:08:50 2003), 转信

这儿再提供一种通过Idl或dll来调用com组件的方法(不用生成*.h和*.c文件)

其实这种方法比通过生成.h和.c文件来调用要简单一些:),还用精华区的例子

1.通过ole/com object生成idl文件,将此idl文件加入工程,点菜单build-complie

comtest_1_0.tlb,生成tlb文件

2.打开classwizard,点右边的add class-from a type library class,选中刚生成的

comtest_1_0.tlb(应该在debug\目录下),其实这儿也可以直接选择用matlab的combuilder

生成的comtest_1_0.dll(这样就省去了第一步),后面将出现生成class的一些对话框,照

提示去做就可以了,这样就生成了comtest_1_0.h和comtest_1_0.cpp,多了一个Isgltest

类:)

3.测试代码如下:

头文件中只需添加:

#include "comtest_1_0.h"

测试代码:

Isgltest st;

AfxOleInit();

if(st.CreateDispatch(_T("comtest.sgltest")))

{

st.im_test();

AfxMessageBox("Haha,Succeeded");

st.ReleaseDispatch();

}

else

AfxMessageBox("UnSucceeded");

上述代码的具体意义参看msdn,我也是刚刚摸索到:)

� 在 promise0608 (promise0608) 的大作中提到: 】

: 我在使用COM组件时,用Microsoft Visual Studio的工具OLE Viewer 打开生成的组件。找

: 到那个用Matlab com builder生成的Dll文件,将其另存为*.h 和*.c 文件时,出现错误!

: 我用的是VC.NET,不知道什么原因!

: 请大家帮帮我!

: 谢谢了!

--

come on,baby!

※ 修改:·xxhn 于 Aug 19 15:12:28 修改本文·[FROM: 218.76.251.27]

※ 来源:·BBS 水木清华站 smth.org·[FROM: 218.76.251.27]

发信人: xxhn (小湖南), 信区: MathTools

标 题: Re: vc中的数组和com中的VARIANT变量的相互转换

发信站: BBS 水木清华站 (Fri May 30 12:58:02 2003), 转信

我再来补充一下,vb,.net中的数组和com中的VARIANT变量的相互转换

vb和.net变量的相互转换也很简单,下面举例简单说一下:

在我们前面的sgltest里面增加一个函数叫y=paratest(x),x,y为输入输出,都为矩阵

1.vb下:

Dim st As sgltest

Set st = New sgltest

Dim x(2) As Variant, y As Variant

x(0) = 3#

x(1) = 5#

x(2) = 6#

Call st.paratest(1, y, x)

y(1,0),y(1,1),y(1,2)就是输出的数组

2..net下:

comtest.sgltestClass st=new comtest.sgltestClass();

object y=null;

object[] x;

x=new Object[3];

x[0]=2.0;

x[1]=3.0;

x[2]=4.0;

pt.para_test(1,ref y,x);

y[0,0],y[0,1],y[0,2]就是输出的数组

� 在 capriccio (俊) 的大作中提到: 】

: 用一个例子说明一下,

: 首先用matlab的m文件描述一下例子中com组件的功能:

: function y=hehe(x)

: y=x*2;

: 把该文件保存为hehe.m

: 用combuilder中建立工程comparatest,加入类paratest,

: 然后加入文件hehe.m,再build成为com组件。

: 下面是vc中的代码:

: #include "stdafx.h"

: #include "stdio.h"

: #import "mwcomutil.dll"

: ...................

--

come on,baby!

※ 来源:·BBS 水木清华站 smth.org·[FROM: 202.113.40.70]

发信人: capriccio (俊), 信区: MathTools

标 题: Re: vc中的数组和com中的VARIANT变量的相互转换

发信站: BBS 水木清华站 (Fri May 30 14:49:09 2003), 转信

关于传递的参数是复数矩阵的问题,

郁闷了好长时间之后突然想到,

没有必要非要搞清楚这个问题(虽然matlab的确提供了复数参数的传递方法)

只需要把复数的实部和虚部作为两个实数参数分别传递就行了。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

发信人: xxhn (小湖南), 信区: MathTools

标 题: Re: 关于com builder一问!

发信站: BBS 水木清华站 (Fri May 30 19:35:07 2003), 转信

� 在 siciliner (fisher) 的大作中提到: 】

: 标 题: Re: 关于com builder一问!

: 发信站: BBS 水木清华站 (Fri May 30 15:28:10 2003), 转信

:

: 没有人帮帮俺么?

:

: 【 在 siciliner (fisher) 的大作中提到: 】

: : 对6.5信有的com builder做了一下测试,发现如果没有调有simulink模型,也就是m文件

: : 里面不包含sim命令,用combuilder建立com组件不会出现问题,但是如果含有sim命令,

: : 就会出错

: : 请教各位,有没有什么好的解决办法,还是combuilder不支持simulink呢

~~~~~~~我想就是这个原因,如下是从matlab

combuilder的帮助中摘下来的

Limitations and Restrictions

In general, limitations and restrictions on the use of MATLAB COM Builder ar

e the same as those for the MATLAB Compiler. See the Limitations and Restric

tions section of the MATLAB Compiler User\'s Guide for details. Note that alt

hough the Compiler supports some usage of the MATLAB input command, MATLAB C

OM Builder does not support this command at all.

而matlab compiler不支持simulink,所以combuilder也不支持吧

: : 多谢了!

:

:

: --

:

: ※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.73.158]

--

come on,baby!

※ 来源:·BBS 水木清华站 smth.org·[FROM: 202.113.40.70]

九.combuilder与vc混编中复数类型的输出(By LPCTSTR)

今天瞎捣鼓了一下,在前辈们的基础上解决了这个问题 ;)

调用com的方法和前面的几位略有不同,个人感觉比他们的简单、正规一点;)

step 1 建立m文件,build成com

m文件写的很简单

function cplx = getcplx()

cplx = 1+2i

方便后面看代码,写出我建立com工程时组建名称:AMyCom 类:MyTst

step 2 导出必要的头文件

1.打开OLE viewer (vc6.0菜单:tools--〉OLE/COM Object Viewer

2.OLE viewer 菜单:file-->view TypeLib

3.打开combuilder生成的dll:AMycom_1_0.dll

4.File-->save as 选择生成 .h文件

5.将生成的头文件拷到vc工程路径下

6.重复以上步骤生成mwcomutil.dll的头文件

step 3 vc下的简单测试源代码如下:

#include <windows.h>

#include "stdio.h"

#include "mwcomutil.h"

#include "Amycom_1_0.h"

void main()

{

CoInitialize(NULL); //初始化com

//创建Com实例

CLSID CLSID_MyTst;

CLSIDFromProgID(L"AMyCom.MyTst.1_0",&CLSID_MyTst);

//这里的ProgID可以在combiulder的component->component info里面看到

邓科峰 dkf03@mails.tsinghua.edu.cn

//或者搜索注册表得到

IID IID_IMyTst = __uuidof(IMyTst);

IMyTst* pMyTst = NULL;

CoCreateInstance(CLSID_MyTst,NULL,CLSCTX_ALL,IID_IMyTst,(void**) &pMyTst

);

////////

VARIANT r[5];

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

{

VariantInit(&r[i]);

}

pMyTst->getcplx(1,&r[0]); //调用函数接口

IMWComplex* pTemp = (IMWComplex*)r[0].pdispVal;//复数类型的接口

pTemp->get_Real(&r[1]);

pTemp->get_Imag(&r[2]);

double dr = r[1].dblVal; //获取实部

double img = r[2].dblVal; //获取虚部

printf("real : %f\nimg : %f\n",dr,img); //

getchar();

CoUninitialize();

return;

}

个人感觉matlab的一部分比较复杂的数据类型都做成了com组建封装在mwcomutil.dll中,当

用OLE viewer打开该文件时可以看到好多接口,其中包括IWMComplex即复数类型的接口,co

m参数的传递通过VARIANT类型来实现,可以在MSDN上查到详尽的用法

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=47426

[点击此处收藏本文] 发表于 2004年07月21日 2:52 PM