QQ登录

只需要一步,快速开始

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

COM应用软件开发技术

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

蔡倩

4 l7 o! G3 r* {! M3 Z5 ?* T( z

主题词: COM ActiveX C++ Builder

% t4 ?2 L; s# v! A; m1 S

1.COM技术概述

5 b. a/ V( V ~

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

/ n; h8 y5 [/ N* R7 \/ x0 ~- N

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

* m/ V# A6 A, k" b4 S! \

◆用于创建ActiveX控件。

6 V/ r* X. d5 S: ]

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

) m% y% N9 D: e9 W7 z7 \* N. L

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

0 o1 I1 L: d- i4 _/ O

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

: m8 w# V2 g+ v2 D+ H2 h

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

6 d! H! p. W! N

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

7 E9 A+ y( M; \

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

8 b* S+ k+ i; i/ N, U$ m

2.建立COM服务程序

% }2 W- B' E- Q5 G8 R) }

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

4 I5 t% f) i7 J% h, C9 e3 S/ W7 A

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

' d, f2 b/ |0 I( `4 p8 M

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

7 H" S, c% h( i! Z! x

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

- E, v, V4 \, E: m

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

& p, I8 W! \ k2 k+ h$ t: b

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

7 E0 y. o) x# |8 r! j! n( K& q

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

9 Q5 I$ u5 |1 m0 w* n

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

/ ~' {$ _7 r4 Z- b6 J) F4 h4 w

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

! u1 f% i9 y1 N9 N! U2 }& T; m

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

% ]- C' x, a. b( p I, Q$ w1 z0 m

2.2建立COM接口对象

@' y3 U, T# Z+ k

7 }( F' p6 D; G

; T, o! O5 f+ h3 G

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

& w2 _9 p) v. {

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

" R' e, P1 U, s# Y& ~

; ]/ }! @/ g3 X' \+ v2 Z9 l( k% j6 }

9 F4 u2 H9 q b8 n& B8 F

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

/ o! ~, T# o4 O5 Z8 a5 v8 w+ J

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

2 ^- L9 A3 P7 r8 N# D$ b/ o

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

& Q9 B" g5 B' f# J( B% ~0 s

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

, _5 s" R0 T# J! B! N2 F

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

6 B) `& O/ Y q

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

$ Q3 a6 }9 i E t5 X

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

9 ~8 n6 a% t; M; o

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

4 x M0 h/ `* G/ y

[id(0x00000001)]

# K* }$ I0 {& d8 E2 ?' Q

! M! P* H+ W! j

+ O, ? E! ?' k# n# |

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

2 i; f* m1 u9 U% e$ S; s {

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

8 A3 ~/ v5 j; T7 f3 [3 x

PCOMServer.TLB: 类型库文件;

) W2 g- T- y4 q! @1 B) ?' z9 D6 d* x; U* P

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

7 I3 E8 L) x. ?: y# r

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

4 J" C, r3 L% P4 R* a

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

5 Q1 k! Q, {1 B1 D

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

' r7 b; C( n( E& [5 B/ p/ Z: r: |

2.4 实现COM接口中的方法

0 h- s0 f3 \" j, Y4 \" n% E1 r

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

5 o4 q! ]5 o2 ], D3 t$ s

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

2 {3 G% | @/ I6 \+ a

{

4 |# V W3 e/ \1 d! E

*ret=x+y;

) N. A1 A9 V8 S/ R

return S_OK;

; J3 F% T! U$ z- X, ~

}

# c% _/ _. P" a, K5 F

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

8 N8 H* a4 H, Z' t

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

1 E% l- `6 o& A

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

; U6 e7 g1 u) N% ]( `3 q) t9 G

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

" W. ]& K6 _8 O( R4 T

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

g& Z, f2 D$ E; o1 v0 D( `

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

* S6 |& m/ [% V2 U1 f

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

% K8 }6 D' k- U3 D( t; E* {+ H

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

/ d8 i* t5 J2 b; W

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

& D& z8 Q6 ]' l" U

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

! T$ f2 i* N4 g, h

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

$ H- C% b4 b2 i F

3.建立COM客户程序

. v+ ~) d9 |: ]1 [

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

8 G" y7 u% K. ` B. L, w8 M

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

6 O, z/ L' W( y& `1 C& N4 R- M8 _

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

. S% T: _5 Z, ?% |9 B* D, m

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

4 M/ u( [8 K9 g( C

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

2 L) m' i. v8 A' u8 Q* Q7 Y

// Helpfile:

' l' M% W% M( }

// DepndLst:

4 q- R. i. E- o) s. M# O

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

' d1 N r7 d2 s( `

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

/ j; d2 v8 k) w1 P

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

3 \. X7 @# S& t/ n! K7 A4 }

#ifndef __PCOMServer_TLB_h__

3 {1 y9 }3 p; q

#define __PCOMServer_TLB_h__

& \1 E0 x( `7 P l1 T) K

#pragma option push -b -w-inl

# T4 ]% E% ]1 c; Q) y8 X" J, T7 e

#include <vcl/utilcls.h>

H. m' y: m5 l8 i* e: H3 ^

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

% _2 v8 m; g% I) ]3 `$ a

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

, Z$ Q8 i }2 f% a, U

#endif

! m. @5 a8 D) I- Q+ p0 a% v

; Y7 [4 z' b$ z1 P0 Z+ e2 H

#include <olectl.h>

4 o) g- D% R5 @5 T) L3 ^

#include <ocidl.h>

; L5 K A. R ]7 }

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

# ]3 s$ E& _7 ^+ n% }& g8 Z

#if !defined(__TLB_NO_EVENT_WRAPPERS)

0 `6 K1 t; n$ H: ~6 {

#include <atl/atlmod.h>

$ h$ e+ m1 W* {" _+ v9 |- {

#endif

1 A- y# {5 s3 T7 y: v3 T

#endif

- |% n; B2 l$ h- l

- r$ O `! C9 T8 G+ n& Z! ?" T

namespace Stdvcl {class IStrings; class IStringsDisp;}

; Z1 b( S/ K _

using namespace Stdvcl;

% m$ U& x; q. e+ ^ U" h

W) C7 S; N1 O$ T& ^) u8 K

namespace Pcomserver_tlb

- f# j! ~; }, h2 z" l2 L

{

6 g. S- n- w9 M$ X+ _% ]9 _

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

' T0 C: l$ e6 \) _" M5 D

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

) g, q- ?% P6 M

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

/ M) G k9 E4 S1 m4 }

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

; }$ c$ K: H0 L+ C2 p' ^: v9 F

typedef IMyCOM MyCOM;

% ~$ Z2 r: f2 g

' V" \6 P# P, k0 N, f' q

#define LIBID_OF_MyCOM (&LIBID_PCOMServer)

, q% ^& ]4 }9 P8 \ b6 i

interface IMyCOM : public IDispatch

) R1 y x5 n) T

{

& Z# _4 U3 D: R! s" ?% A

public:

3 K' S6 U" H! S& P/ I

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

) [1 |) Z$ }) y: \+ f

#if !defined(__TLB_NO_INTERFACE_WRAPPERS)

5 y7 x ]+ W5 I

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

$ p8 z( W. A: W+ q

{

4 p+ v. ~8 O* c- C- `+ ]* G

int ret;

/ x4 ~4 g3 U2 |$ A/ S

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

' v1 @8 |! `5 W

return ret;

5 T; J0 ~6 b# N5 j+ ?$ Q2 R2 |+ q

}

7 |/ q. J1 h: O8 P& b2 R

#endif // __TLB_NO_INTERFACE_WRAPPERS

0 e# c7 U5 x v* _+ m. G" N# F

};

) z4 [) }+ y9 D8 f- W

#if !defined(__TLB_NO_INTERFACE_WRAPPERS)

+ r8 \! l- |6 K9 `) U

template <class T /* IMyCOM */ >

0 J O* y$ t, x6 ]' n& c2 w

2 m' L" o# y) P$ ^: V* I

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

2 I5 M, J- T3 n! C/ K

{

$ l; X8 L* L, z7 z* M4 @

public:

T4 D% J+ a3 ?$ s3 g1 T

TCOMIMyCOMT() {}

( h' ?' ~6 Y' w+ [! ^

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

/ Y* [( S# [2 ]# A( z8 S1 R

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

0 f7 l' O" j: G& X

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

& y$ Z+ r. m' Y

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

% u: y5 ~$ Z. {2 K3 r) p

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

& [- z1 O# j" w

};

) T1 o6 D9 I' t: t" U

typedef TCOMIMyCOMT<IMyCOM> TCOMIMyCOM;

" J- G6 K" V9 Y( _, m& G

0 d* Z0 E8 T0 |; o& |9 S( s

template<class T>

6 T6 y' P. c' S* \

class IMyCOMDispT : public TAutoDriver<IMyCOM>

8 M- R6 }9 t( t7 `% \* c/ L

{

7 _& X7 i3 u0 Z* O: ?; V

public:

6 ^; _! g8 {4 H

IMyCOMDispT(){}

! }' w5 Z1 ~# c4 c1 I9 J6 e9 Y

IMyCOMDispT(IMyCOM *pintf)

0 ^# f7 h& G; F3 K( `6 Q" x

{

$ `" k7 r$ }. d: L# E/ H

TAutoDriver<IMyCOM>::Bind(pintf);

4 P$ j. C9 k, }8 x4 E/ h- Q

}

" }$ h8 A" k0 D3 @# D% U

IMyCOMDispT& operator=(IMyCOM *pintf)

+ `' s- u. H- F6 o% B8 c# C

{

1 L" b* B; H+ o/ O

TAutoDriver<IMyCOM>::Bind(pintf);

0 Z9 S2 @) ]8 W n

return *this;

$ o. k! p- `2 {, j: A9 U7 A% F

}

$ L# f q' y% Q: E# {. ~6 q

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

, N4 L' l3 {; X

{

! I3 K+ p: ]. g# t2 Y$ i) U

return OLECHECK(Bind(CLSID_MyCOM));

4 a6 t: l4 x `* q9 j ?

}

1 n ]# K" }6 T, d9 O' h: O

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

- e# v9 v, J/ w# N( x6 P- l2 T. [

{

/ V4 ?* o9 y* Z% o7 j! `4 L/ H5 c2 i

return BindToActive(CLSID_MyCOM);

) ~6 g5 c" [( Y) ~. l

}

J5 `! z2 U6 x' r

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

8 y: q( u5 d4 W+ ?

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

- D( C% B7 [$ f, U7 ?; [1 |* `, V; o

};

8 ^6 T% W* S: ?# k. \

typedef IMyCOMDispT<IMyCOM> IMyCOMDisp;

4 T9 o6 c0 W) a( T$ i1 D

. I7 W1 j/ h1 H5 n/ q

template <class T> HRESULT __fastcall

5 ?, j' j; Q$ q

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

$ n/ s( a' [- J; w3 R) w

{

9 v% [& D7 a& C1 Z& T1 s/ g3 q

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

7 ?, ?4 D$ z z# T

}

& x' R7 a& l! P

' R$ H; b5 I, z" T

template <class T> int __fastcall

) z! G: z/ D* M* k; b* L+ W! T( D

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

" }4 Z( t( \) |2 y2 m7 X+ u

{

4 S: J- J- s7 Y) H! ^- T; t

int ret;

* T* z" L& C7 n, E& j& [

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

8 J4 R% x. T; H0 e1 H) v

return ret;

7 ~! V% J4 ~- Y6 v+ J" m/ v7 N

}

1 c: ^7 M. _: A7 z5 d. a+ `

6 D# k' N+ n8 r: o" t

template <class T> HRESULT __fastcall

$ I) ]& l$ [/ _3 v$ g* C9 }

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

. c- ~8 Z Y, z1 u9 \' i! t

{

# M$ q/ N3 w- y5 ^- R ], H7 L

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

. q/ |% ?- o. i0 v |0 I

TAutoArgs<2> _args;

& @# B/ ~: g0 [/ K. v

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

7 P+ h( A3 ~6 B1 F, a

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

% a3 G5 B6 M9 O8 ]4 U

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

4 c' v# E# S. l2 A" x) a0 H

}

0 a/ n& e$ Y/ J1 x7 _

0 D1 d4 k4 f$ l7 ^4 ?0 z* B8 N

template <class T> int __fastcall

) Q+ I; h2 q) l7 s/ K" v$ F

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

& H: R$ m1 ]8 G4 _

{

1 _' C6 L1 }+ b" W. O

int ret;

' U( N- [) V' ^: L9 C' ~2 i0 L

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

5 A, ^! Q$ f* \6 T1 w

return ret;

% D; z9 a4 S( y( m/ {4 k& ?7 v

}

- U7 ~1 s. h3 _, D+ n& _

& c, ]9 P5 R/ S+ z8 E I7 v

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

3 V9 m' C! ]6 b* N/ Z/ f( F

#endif // __TLB_NO_INTERFACE_WRAPPERS

3 `' Q% y, j$ G7 C. v

}; // namespace Pcomserver_tlb

% J9 t! [) E1 g

#if !defined(NO_IMPLICIT_NAMESPACE_USE)

. M" S% b5 i9 b8 u

using namespace Pcomserver_tlb;

% y/ O* o8 Q2 g+ s( A8 s3 G9 a* i' Z

#endif

0 D% a4 J5 f! B' m* @. d

#pragma option pop

3 ~9 j! ^" E% v4 H" B

#endif // __PCOMServer_TLB_h__

+ J" c, p1 B9 v) M+ n y; t( I

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

0 S0 f. c! v5 s

interface IMyCOM : public IDispatch

* D) a5 A. D, P; ^

class TCOMIMyCOMT : public TComInterface<IMyCOM>

! W4 g' Q( N1 V

class IMyCOMDispT : public TAutoDriver<IMyCOM>

/ j% {' J0 T: j0 Z# T" U

class CoMyCOM: public CoClassCreator

& ]/ w" Z# p0 r) `* y% C1 g

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

# E3 G3 ]' p, G. L* ^

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

' Q$ d' v5 `+ n" T) ~

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

% Q; ]# S+ R7 |7 D7 p3 y4 f

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

2 J1 ^1 N4 n, q5 d; {) G' K* C! u

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

7 f- j& h4 C6 ?8 U# {5 B+ N

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

3 j8 o- ~. b8 V" d- V' T

int x=6,y=6;

! d, l( U: {" n

TCOMIMyCOM O;

1 A- }5 ]0 \1 Z% L) M

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

w: D6 P9 O5 o7 d7 t: @! z

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

^" D' ^; }- {; q) ]

Edit1->Text=IntToStr(y);

! ?) Q6 p! N* H d

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

& T& A0 B) D, U$ `5 S' U

int x=6,y=6;

, c/ K+ Q. W' `5 p" |' C# f

IMyCOMDisp app;

. h9 N# z' l, t% u) l

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

2 ]+ i* G; ^1 T. ~4 k8 ^

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

, a! w. U \; l e6 y

Edit1->Text=IntToStr(y);

% \; j/ L( B# c' j

4.小结

" N: \7 g7 K# \: J9 E

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

7 x" s& {+ \7 B% G1 Z: ?! X# o

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

/ T7 v3 }+ P; @, ~

/ c @1 \1 o2 K9 z% s$ t- g

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-4-18 15:51 , Processed in 0.282437 second(s), 52 queries .

回顶部