QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1858|回复: 0
打印 上一主题 下一主题

COM应用软件开发技术

[复制链接]
字体大小: 正常 放大
韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

跳转到指定楼层
1#
发表于 2005-1-26 01:07 |只看该作者 |倒序浏览
|招呼Ta 关注Ta

蔡倩

: p0 \1 z5 p4 O( N% I4 y3 f

主题词: COM ActiveX C++ Builder

( `1 } P( y2 l5 v: u4 \

1.COM技术概述

& m% \, d7 {. N, g4 k

COM表示Component Object Model(组件对象模型),它是Microsoft大力推广的软件开发技术。采用COM规范开发的应用软件具有强大的功能,主要有如下几点:

; j0 M- Q9 J% I8 o( k& [/ k

◆COM是二进制编程规范,可以编写被多种语言使用的代码。

/ j4 w* g/ M+ M

◆用于创建ActiveX控件。

1 H2 j+ x5 Q/ G0 w; X4 o

◆通过OLE Automation 控制其它的程序。

* j) X( M" j' \2 E: X- [, I/ t8 }

◆与其它机器上的对象或程序进行对话,构成分布式应用程序。

& q4 h" r$ V+ P! }

Microsoft推出Windows 98和Windows NT 5.0后,整个操作系统的核心都围绕着COM来建立。我们可以把Windows系统看作是一系列的COM接口,在需要是可以调用这些接口。如DirectX就是一系列的COM接口服务程序,通过它可以进行高性能的Windows图形程序设计。

% `: L1 X6 R# F. w) S

用COM技术开发的应用程序从理论上说是客户/服务器模式的程序。程序员可以使用一系列的COM服务程序来构造他们自己的应用程序,这些服务程序可以根据需要随时嵌入到主程序中。在分布式系统中,可以通过网络来访问这些服务程序。将来,操作系统和整个网络可能会被看作是一套以COM对象形式提供的服务集。一部分程序员负责建立这些服务,而另一部分程序员只负责如何调用它们。其目的是实现软件的即插即用。

# D9 k/ m: l" T: {

开发COM应用程序是比较复杂的,通常需采用ActiveX模板库(ATL)来编程。在这里我们推荐采用C++ Builder来开发COM程序,Inprise(Borland)公司的面向对象技术一直处于世界领先水平,C++ Builder采用可视化方法,隐藏了ATL的实现细节,自动生成COM接口所需的代码。

9 p9 }' J7 S3 M( Y; s- _

以下的程序举例采用C++ Builder 4.0 编制,在中文Windows98环境下运行。

6 m' B2 k# R/ I; N- H/ @, B, M

2.建立COM服务程序

1 Q% [" {) Z3 p6 F' m7 d

COM服务程序有三种形式,第一种是驻留在本地机器上以DLL形式提供,该服务程序被调用时,嵌入到调用程序的线程中运行;第二种是驻留在本地机器上以EXE形式提供,该服务程序被调用时将占用独立的线程运行;第三种驻留在远端机器上以EXE形式提供,服务程序通过网络被调用,它在远端机器上运行,结果通过网络返回调用者。

) R! D+ `" A7 w" E6 `

在此采用第一种形式建立COM服务程序,这也是最常用的形式,DirectX就是采用这种形式提供的。

( y# x8 |, ]7 }4 H

C++ Builder建立COM服务程序的方法如下:

! q/ y% L8 q! ~' M

2.1创建支持COM接口对象的动态连接库文件:

D8 i, Q* q) P0 \6 A

◆打开File/New/ActiveX项目页,选择ActiveX Library;

1 {( e, I) f Q3 ~7 Y

◆选择Save All 将项目以PCOMServer文件名保存;此时C++ Builder 自动生成如下的文件:

2 E$ D& h# z8 K& @6 I- u

PCOMServer.bpr:工程的项目文件;

* P! h) R8 Y0 F3 `' |6 q2 g

PCOMServer.h,PCOMServer.cpp:支持COM对象的动态连接库源文件,其中有许多函数用于COM接口对象的自动装配,大家不用去编辑它们;

' N% R0 L/ [: I1 d

PCOMServer_ATL.h,PCOMServer_ATL.cpp:ATL形式的文件供C++ Builder编译器调用,大家也不要去编辑它们。

) t! Z; B8 u, c1 v1 U7 P4 B, L- I

◆打开Project/Options/Linker 属性页不选中Use dynamic RTL选项,打开Project/Options/Packages属性页不选中Builder with runtime packages选项,这两步操作可以使开发的COM动态连接库不依赖C++ Builder的VCL动态连接库,有利于独立发行,但在一般情况下还是建议选中这两项。

# K- z* j$ F" y

2.2建立COM接口对象

+ ? t( l. S" J& w

$ S3 F7 R1 q5 T4 O q

' B: d1 H, D' p6 D, h2 B& a, O' p+ r2 k

打开File/New/ActiveX属性页,选择Automation Object表示向服务程序中插入一个自动类型的COM对象,我们选择这种类型的COM对象是为了可以自动注册,并且自动支持可以被其他语言调用。此时出现如下的对话框,输入COM类的名字MyCOM即可,对话框中的其它选项用于规定COM对象的性质,可查看帮助信息。

( F) n0 J# _4 r- A; X% c, c

2.3通过类型库编辑器编辑COM对象中相应接口对象的属性和方法

- M+ ^3 D+ {$ m6 R L% `

- t- }8 g6 L2 i+ Z5 f

* i3 Y* u5 n! f& r9 M

此时自动进入类型库编辑器,类型库用于存储COM对象的说明,是一个可以被多种语言调用的头文件包。在类型库中,可以定义COM对象的接口,定义接口对象的属性和方法等。类型库编辑器如下所示:

" B0 `+ ? Z. V/ N" a3 ~

可以看出此时自动产生了MyCOM类的一个接口类IMyCOM,在COM应用软件中我们实际上是与接口对象打交道,下面通过类型库编辑器为IMyCOM接口定义方法和属性。

4 e- {2 W# x) q2 }# ~8 B

◆单击编辑器顶部的Method按钮;

2 z1 d4 G- i, q. ^

◆在Arributes页面的Name字段中输入方法的名称,本例中是AddInt用于整数加法;

8 ?2 D) B [. Y; Z

◆在Parameters页面中,单击Add按钮编辑方法中的参数;

0 F2 `: v! t8 r$ b6 L

x和y是输入的两个整数,ret用于返回运算的结果,必须定义为指针型

# n& k0 j4 I! L; E; T% m) L3 w

◆切换到Flags页面,可以对接口的属性作调整;

3 Z, O. M5 \* d n

◆在Text页面中可以检查生成的IDL代码:

, Z# |" m1 A( k0 p, B

[id(0x00000001)]

1 c4 u7 v" p& x8 Q0 m' y* a

7 \& j' U2 E5 A

- l/ W# N1 Y# e1 f) `# Q( H; Z

HRESULT _stdcall AddInt([in] int x, [in] int y, [out, retval] int * ret );

3 \/ l! Q* H7 G! p, c: \

◆单击Refresh按钮,此时可以关闭类型库编辑器。当需要为接口添加新的属性和方法时,可以通过View/Type Library重新打开编辑器。选择Save All用C++ Builder提供的缺省文件名保存类型库的相关文件如下:

w. Y8 r' {1 A* I

PCOMServer.TLB: 类型库文件;

7 d0 W& \3 R4 I8 q8 A- y

PCOMServer_TLB.cpp:包含COM接口和对象的说明,其主要目的是方便访问,在客户程序中需将本文件包含到客户程序的工程中;

7 V3 n" A H! f: @. I3 ?* J

PCOMServer_TLB.h: PCOMServer_TLB.cpp的头文件,通过#include引入到客户程序中。

9 f6 d, I0 T' d) p' J- m9 M4 r

MyCOMImpl.cpp: 该文件是我们需要编写程序代码的地方,实现类型库定义的接口对象的方法和属性;

4 B, V+ n b) V5 I, f1 j# q7 I: S

MyCOMImpl.h: MyCOMImpl.cpp的头文件。

5 F. x4 v, m" l

2.4 实现COM接口中的方法

/ ?- d, }, }: w* ~1 A9 a

打开MyCOMImpl.cpp文件会发现我们在类型库编辑器中定义的方法,为该方法编写代码如下:

! u) J/ h4 \' ~- o; C

STDMETHODIMP TMyCOMImpl::AddInt(int x, int y, int* ret)

# b2 g8 Q+ ]6 L8 F/ H* N b

{

n+ c' C' y7 z* J) g

*ret=x+y;

+ K+ t3 G. ^% i8 ~4 X

return S_OK;

5 Z( c2 i* f1 s, |

}

; S" ~ C h5 |( i3 M3 q

2.5 生成DLL文件并注册COM对象

- y. _: Q, F0 R2 e

◆选择Project/Builder PCOMServer 生成PCOMServer.DLL文件。

N5 ~( h/ R. [; d

◆打开类型库编辑器,单击Register按钮完成对COM对象的注册。

, a- c$ a, N/ x6 I

通过Windows任务栏中的Run菜单运行REGEDIT程序,在Windows注册表的HKEY_CLASSES_ROOT键下查找到PCOMServer.MyCOM子键,PCOMServer为DLL文件的名字,MyCOM为COM对象的名字,在下面可以看到该COM对象的全局唯一描述符CLSID如下:

! h2 J2 B L8 {/ R* B- K$ z3 i

{59834F03-49F1-11D3-B85B-00E09804A418}

3 ^, z1 |& V1 g$ W) w; f

注意:不同的机器生成的描述符不同.

* z2 `, s+ i0 P# k# e% x/ a

在HKEY_CLASSES_ROOT键下查找到CLSID子键,在它下面找{59834F03-49F1-11D3-B85B-00E09804A418}子键,下面有如下的条目:

* r# k! j- O; I" a" q7 D: M4 d

InprocServer32:存储PCOMServer.DLL的路径目录;

4 q5 Z2 D- r8 m& C' ?1 r6 {

ProgID:存储COM对象的注册名:PCOMServer.MyCOM;

, H% b h: e" c+ f

Typelib:存储COM对象的CLSID值{59834F03-49F1-11D3-B85B-00E09804A418}。

" \. R( }: x' |! k) V {

COM对象就是通过在注册表中的纪录实现DLL与客户程序的自动连接。

* c7 |' y, T' a6 c

3.建立COM客户程序

' c6 r; n L2 }

客户程序将访问PCOMServer.DLL服务程序中的MyCOM对象,这些对象的说明保存在前面所述的TLB文件中。我们可以直接将PCOMServer_TLB.cpp加入到客户程序的项目文件中,并在客户程序中引用PCOMServer_TLB.h文件;也可以通过Project/Import Type Library引用PCOMServer_TLB.TLB文件,重新生成.cpp和.h文件,自动完成上述过程。

( C2 R: e( b* B! `: | L

客户程序的编程重点是实现对服务程序中COM对象的方法的调用,调用的方法有多种,都是通过所谓的代理接口来完成的,这些代理接口在PCOMServer_TLB.h中有详细的定义,从这些定义中可以看出这些代理接口调用对象方法的过程。

6 p% N! h9 E' r* c, y$ M) m3 l

PCOMServer_TLB.h文件很重要,包含了调用MyCOM对象的各种接口信息,该文件主要内容如下:

5 Q: r2 t+ w9 X1 ?4 Q

// Type Lib: D:\CAI\com\PCOMServer.tlb

# ^- l. z/ c( }6 x' B" P6 @9 n

// IID\LCID: {5BD378E5-4B57-11D3-B85B-00E09804A418}\0

& P/ ~9 G+ Y7 W1 S

// Helpfile:

7 A. M# X$ h( k- M- D

// DepndLst:

" y6 K1 W {: Z: J

// (1) v2.0 stdole, (C:\WINDOWS\SYSTEM\STDOLE2.TLB)

/ ], V% t" I b: p' p( W$ J

// (2) v4.0 StdVCL, (C:\WINDOWS\SYSTEM\STDVCL40.DLL)

7 w, r% {2 V% S) w

// ************************************************************************

% Z# v) I" P# y" Q8 K

#ifndef __PCOMServer_TLB_h__

Q7 T8 [/ z$ T

#define __PCOMServer_TLB_h__

5 v, c/ ?3 b3 \* O

#pragma option push -b -w-inl

6 Y0 S8 u; j7 a& s5 s

#include <vcl/utilcls.h>

0 F; O1 I' H, x% n( v

#if !defined(__UTILCLS_H_VERSION) || (__UTILCLS_H_VERSION < 0x0101)

0 N: K2 ]3 s. f$ t+ ]; f

#error "This file requires an newer version of the header file UTILCLS.H"

8 L+ }2 o! K' |! x L& ^

#endif

- W; x) B! e4 R7 X0 x5 k

# ~* C) m& P" C' ^0 I' m1 O7 d

#include <olectl.h>

: p3 |- w6 r. d9 _) l( Q$ C N7 u* ?

#include <ocidl.h>

% B; B( q, W, A# V

#if defined(USING_ATLVCL) || defined(USING_ATL)

; I- O/ I @: z# k3 X% J0 E( K& g" u

#if !defined(__TLB_NO_EVENT_WRAPPERS)

$ m ]% Y& L# q4 t! z: V

#include <atl/atlmod.h>

* V/ S3 p6 [- S

#endif

3 T' r% G( w4 \( y( O7 v

#endif

! f3 A. E& m+ W6 Y( a

. r& Z# O1 ?$ G; j2 L2 w

namespace Stdvcl {class IStrings; class IStringsDisp;}

; ^3 }3 M/ z2 ]$ M4 p

using namespace Stdvcl;

' E+ d0 x6 M8 k$ n

P- c# z" Y5 F; h) S9 g% {

namespace Pcomserver_tlb

. B! n- M' i. v

{

1 L/ w+ f# _$ s2 ], k- c; Q) `

DEFINE_GUID(LIBID_PCOMServer, 0x5BD378E5, 0x4B57, 0x11D3, 0xB8, 0x5B, 0x00, 0xE0, 0x98, 0x04, 0xA4, 0x18);

! U+ M$ o6 b% c& B% `$ c2 u

DEFINE_GUID(IID_IMyCOM, 0x5BD378E6, 0x4B57, 0x11D3, 0xB8, 0x5B, 0x00, 0xE0, 0x98, 0x04, 0xA4, 0x18);

- }! k: }5 B' ]6 v

DEFINE_GUID(CLSID_MyCOM, 0x5BD378E8, 0x4B57, 0x11D3, 0xB8, 0x5B, 0x00, 0xE0, 0x98, 0x04, 0xA4, 0x18);

6 L) F& v. B0 K9 u' y2 B

interface DECLSPEC_UUID("{5BD378E6-4B57-11D3-B85B-00E09804A418}") IMyCOM;

9 p& g- P) @1 p

typedef IMyCOM MyCOM;

3 M" `* S% v+ Z3 X* D) j

3 V) A* S% H+ w5 _. d0 W" a" m

#define LIBID_OF_MyCOM (&LIBID_PCOMServer)

: w4 s, M! Y! w7 ?4 b% B

interface IMyCOM : public IDispatch

2 T% J! K' e$ w! E7 t

{

* }: W4 p- E" v* x1 a

public:

- E5 ]2 g' d: m; y$ j4 q' f9 _

virtual HRESULT STDMETHODCALLTYPE AddInt(int x/*[in]*/, int y/*[in]*/, int* ret/*[out,retval]*/) = 0; // [1]

' D8 Q G' f0 _

#if !defined(__TLB_NO_INTERFACE_WRAPPERS)

, s# g1 h3 x$ `/ p3 Z: p5 l

int __fastcall AddInt(int x/*[in]*/, int y/*[in]*/)

l3 ]; K) P3 }

{

2 y0 s- M6 v3 M) B' n# K

int ret;

6 i, K6 m0 W; m' x, L

OLECHECK(this->AddInt(x, y, &ret));

0 T# q- T7 E( n# p2 U

return ret;

& L# W5 ?* n7 a& O, p6 {# U

}

! c* B) T* U! z% a

#endif // __TLB_NO_INTERFACE_WRAPPERS

, ?7 [( j% O& W2 D

};

0 z% C- I" `, V3 Y

#if !defined(__TLB_NO_INTERFACE_WRAPPERS)

# Q. x" w8 z+ W% x5 t

template <class T /* IMyCOM */ >

; z. N8 R% }; Q% V

8 T" ~/ t: o v* V( C0 w

class TCOMIMyCOMT : public TComInterface<IMyCOM>, public TComInterfaceBase<IUnknown>

& Z B" h# C/ I

{

" v4 y- f( @6 U% }2 ]

public:

$ p: \ T3 l& [" \4 `2 b

TCOMIMyCOMT() {}

9 x, @+ L2 D/ y0 M9 E' p5 A

TCOMIMyCOMT(IMyCOM *intf, bool addRef = false) : TComInterface<IMyCOM>(intf, addRef) {}

4 x4 ^- o& I0 }0 D

TCOMIMyCOMT(const TCOMIMyCOMT& src) : TComInterface<IMyCOM>(src) {}

5 ]- d, a. t7 L8 h7 M/ M% A

TCOMIMyCOMT& operator=(const TCOMIMyCOMT& src) { Bind(src, true); return *this;}

% a/ c7 w( a- D. I8 f, l/ ^

HRESULT __fastcall AddInt(int x/*[in]*/, int y/*[in]*/, int* ret/*[out,retval]*/);

0 }7 K. o) M' o% K+ s& b

int __fastcall AddInt(int x/*[in]*/, int y/*[in]*/);

6 r3 c2 W- s# v& H8 `

};

* q- Z& y8 O2 s5 T0 o% @ g+ C+ B

typedef TCOMIMyCOMT<IMyCOM> TCOMIMyCOM;

4 N( L" @2 R8 r- f$ i. {

# b. o1 z/ Y- c% A7 L5 ]) @9 S

template<class T>

0 g8 ?& E+ G5 c

class IMyCOMDispT : public TAutoDriver<IMyCOM>

/ w' G( N0 @3 @; H) g& Z2 M+ f

{

/ J" w& d6 s1 s, Y

public:

# u/ x6 j; }4 u: E4 ~$ m& k

IMyCOMDispT(){}

6 a- \. _ }0 j x* ^8 T$ Z

IMyCOMDispT(IMyCOM *pintf)

4 h7 G( v2 T8 E9 E

{

6 B. D4 ~1 h) Z1 e) N

TAutoDriver<IMyCOM>::Bind(pintf);

; P5 A4 |! ~5 a; u

}

- g7 x' y h- c) j) P1 f

IMyCOMDispT& operator=(IMyCOM *pintf)

3 V# N) g1 G1 ^! I5 C" [

{

; X$ q' Y- A" F! q

TAutoDriver<IMyCOM>::Bind(pintf);

/ E: S; C/ a; v0 Z w- ]5 E4 l

return *this;

$ V$ O/ J @7 w+ B7 E' g) [# |

}

" o. t) w. |) {5 A; L

HRESULT BindDefault(/*Binds to new instance of CoClass MyCOM*/)

0 M. Z3 p; O: `* P, Z, y% T

{

; a, R9 N s/ q/ k

return OLECHECK(Bind(CLSID_MyCOM));

& H! c& g2 ]# `1 H9 U" f" \

}

- S! u4 g$ F9 Y T' [

HRESULT BindRunning(/*Binds to a running instance of CoClass MyCOM*/)

8 E+ x8 b' }& Q0 N9 {4 Z7 @. _

{

$ v6 M$ G x E* f) A8 Y

return BindToActive(CLSID_MyCOM);

/ a x8 Z6 F6 L2 H0 Q, V- w B q

}

$ J6 n; ~: [9 |# \/ g6 y

HRESULT __fastcall AddInt(int x/*[in]*/, int y/*[in]*/, int* ret/*[out,retval]*/);

- t; x) Q- |3 h6 I. q

int __fastcall AddInt(int x/*[in]*/, int y/*[in]*/);

3 e* U/ x( _8 }- b8 g

};

' P5 z, O2 N' u! O+ }

typedef IMyCOMDispT<IMyCOM> IMyCOMDisp;

6 L& b* ^, l7 k+ s

0 C$ C# v0 ?5 Q0 x @+ M8 P( o: S

template <class T> HRESULT __fastcall

, [# L( J( L+ A/ Y: K

TCOMIMyCOMT<T>::AddInt(int x/*[in]*/, int y/*[in]*/, int* ret/*[out,retval]*/)

; b2 X, m9 |9 i: \" i! P8 M

{

) P ~3 {; Q$ e) W+ U( N0 A

return (*this)->AddInt(x, y, ret);

3 p3 d U9 Q* r+ w

}

& f# Z* y6 n3 p0 f6 P7 ]

_; Z, I0 N2 I5 {) Y1 d

template <class T> int __fastcall

. g0 P: G! x* \$ X5 D

TCOMIMyCOMT<T>::AddInt(int x/*[in]*/, int y/*[in]*/)

2 [+ J& O1 f" p2 w* ^' v, a

{

; T0 q: q) a: B* M

int ret;

' J3 V! b0 J$ I- G

OLECHECK(this->AddInt(x, y, &ret));

- b+ o' ~. g! H- M

return ret;

8 Q M( A4 ]; @0 D4 i, f

}

3 t7 Y; T% ?1 M+ S

% C' B1 O( G' [1 v& O( a5 B- Y& ]; m

template <class T> HRESULT __fastcall

2 |4 G( o1 X; _$ D

IMyCOMDispT<T>::AddInt(int x/*[in]*/, int y/*[in]*/, int* ret/*[out,retval]*/)

( A# I, \2 ?$ z& I" D

{

5 y9 m& Z- C% i9 l2 A) C

static _TDispID _dispid(*this, OLETEXT("AddInt"), DISPID(1));

; M0 p7 g0 Y4 B+ o& a

TAutoArgs<2> _args;

A2 i& Z+ {% M& B' {

_args[1] = x /*[VT_INT:0]*/;

: Z1 G& k& t/ {( ^. Z

_args[2] = y /*[VT_INT:0]*/;

" E* p, E5 `( @: N0 {8 a1 |

return OutRetValSetterPtr(ret /*[VT_INT:1]*/, _args, OleFunction(_dispid, _args));

2 I$ [6 I0 g6 v

}

9 ?2 j7 i" l1 K: ~6 s- `

8 p( \# t% h5 r: g5 a0 w+ P

template <class T> int __fastcall

* w, v+ C c* T

IMyCOMDispT<T>::AddInt(int x/*[in]*/, int y/*[in]*/)

- O Z; c R) A; n! R F* e8 B

{

, ]$ A" b1 X# J" D

int ret;

2 x# t6 e& ?4 V; e$ Z% N- C/ Z

this->AddInt(x, y, &ret);

; J* z) B7 Y0 a1 U) m

return ret;

& V% e1 c7 u& W- E/ C

}

5 G. K: I8 ^ Z; A

9 C, R8 K. Y+ g2 r- W

typedef TCoClassCreatorT<TCOMIMyCOM, IMyCOM, &CLSID_MyCOM, &IID_IMyCOM> CoMyCOM;

8 q: Z& c# P9 B

#endif // __TLB_NO_INTERFACE_WRAPPERS

* Z8 K+ @6 `, T7 W& u3 ?

}; // namespace Pcomserver_tlb

( ~0 s9 `8 f* G

#if !defined(NO_IMPLICIT_NAMESPACE_USE)

2 R7 v" K4 M3 U% S& n4 x

using namespace Pcomserver_tlb;

Q. Y+ c/ T9 J: x. M

#endif

) B4 e4 i; R" |3 c

#pragma option pop

& H+ |6 L- ~# g3 f! y% k2 L

#endif // __PCOMServer_TLB_h__

' K. j% e. E5 J4 W% O$ T

下面是文件中说明的主要对象及其定义:

2 A" e& k* L4 t$ [" G

interface IMyCOM : public IDispatch

, ?+ \- G, b; C* j8 a8 V" y4 x$ F- K

class TCOMIMyCOMT : public TComInterface<IMyCOM>

, i* t* ], g7 p

class IMyCOMDispT : public TAutoDriver<IMyCOM>

8 ?4 X$ ?5 B+ C& G; ^, U

class CoMyCOM: public CoClassCreator

) n; W# @- `" `" o% z( r& y- _: y4 Y: |

◆IMyCOM:通过IDispatch接口来调用对象的方法,该接口可以使对象被不支持虚拟函数表(VTable)的语言(如Visual Basic)说调用。这是一种很慢很苯的接口调用方式。

# z4 }9 R" b( J, @# d: b% T

◆TCOMIMyCOMT:通过所谓的智能接口来调用对象的方法,既可以实现IDispatch调用,也可以采用VTable进行调用,从而实现最快的调用速度。

4 X# D: z% a# M) g

◆IMyCOMDispT:通过disp接口来调用对象的方法,可以提高Idispatch接口的访问速度,但还是比不上VTable接口。

. ~; k; d' }/ B3 c9 C# B+ {

◆CoMyCOM:通过使用CoClassCreator可以自动产生TCOMIMyCOM代理的实例。

) ~0 s% g3 h" H& h

下面介绍一下实现智能接口和Disp接口调用的客户程序。这个客户程序很简单,有两个按钮分别完成两种接口调用的方法,一个编辑框显示结果。

8 n1 }! q5 ^7 |' L( T* d+ ^# X

◆智能接口的VTable调用方法如下:

0 B4 K4 M3 c* K0 S4 R# S, C6 z

int x=6,y=6;

. g4 t+ H8 |8 n+ i; x& G

TCOMIMyCOM O;

2 X& u; f% A# d+ ?. q

O=CoMyCOM::Create(); //通过CoClassCreator完成初始化

$ q5 H& I8 N0 \+ S, O: T M0 D

O->AddInt(x,y,&y); //Vtable形式调用

5 i1 z9 _+ l; H2 a! q5 p# s

Edit1->Text=IntToStr(y);

* A/ g- `4 s: }- k! f5 P& w$ {0 s

◆DISP接口的调用方法如下:

9 {$ {7 p9 ^; R. C5 l0 I) E1 ~

int x=6,y=6;

; Z5 _$ z6 X' ^3 X/ l4 y3 `, O ~) m

IMyCOMDisp app;

9 p6 m' g; e0 D

app.BindDefault(); //通过Bind完成初始化

9 Q" W' ~- o3 Q9 H4 G/ T, V- W

app.AddInt(x,y,&y); //Disp形式调用

1 D) X4 E( f+ Z q' o

Edit1->Text=IntToStr(y);

" T$ g" t: [5 C) F; u

4.小结

7 R2 x! W* d* N; D e. t) k

上面的程序举例是很简单的,但却详细说明了COM应用软件的开发过程。COM技术不是一个编程语言,而是一种编程规范和方法。采用COM技术可以开发功能强大的软件,有利于分布式应用技术的实现,有利于多人合作开发,也可以帮助我们理解Windows系统本身。COM的接口技术是比较复杂的,想进一步了解COM技术可参阅清华大学出版社的《COM技术内幕》一书。

6 b# F) Z) e2 e( Y7 T/ f3 y+ j# ^

C++ Builder是开发COM应用软件的好工具,它隐含了COM实现的细节,我们只需与它打交道就可以开发完善和强大的COM应用程序。希望有更多的人转到COM应用软件的开发上来,COM技术是软件技术未来的发展方向,是实现软件工程中软件即插即用的有效途径。

+ u0 N% H) H8 n# ?

* C; { I9 D* j! P3 g" \5 E

zan
转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
您需要登录后才可以回帖 登录 | 注册地址

qq
收缩
  • 电话咨询

  • 04714969085
fastpost

关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

手机版|Archiver| |繁體中文 手机客户端  

蒙公网安备 15010502000194号

Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

GMT+8, 2026-6-12 22:34 , Processed in 0.465637 second(s), 52 queries .

回顶部