COM(Componet Object Model_组件对象模型)技术概述
转载FDCFDMin 最后发布于2018-09-07 20:33:55 阅读数 2065 收藏
https://blog.csdn.net/weixin_39743893/article/details/82500563
展开

微软官网链接:
https://docs.microsoft.com/zh-cn/windows/desktop/com/com-technical-overview

简介COM
微软组件对象模型(COM)定义了用于创建在运行时交互的可重用的软件库的二进制互操作性标准。您可以使用COM库,而不汇编成应用程序的需求。COM是许多微软产品和技术,如Windows媒体播放器和Windows Server的基础。
COM定义了适用于多种操作系统和硬件平台的二进制标准。对于网络的计算,COM定义了在不同的硬件平台上运行的对象之间的标准线格式和协议进行交互。COM是独立于实现语言,这意味着您可以通过使用不同的编程语言,如C ++和那些在.NET Framework创建COM库。
在COM规范提供了所有的基本概念,使跨平台的软件复用:
• 对函数的二进制标准组件之间的调用。
• 一种功能强类型分组到接口的规定。
• 一种基站接口,提供多态,特征发现,和对象的生存期跟踪。
• 唯一识别组件及其接口的机制。
• 一个组件加载程序从部署创建组件实例。
COM有许多一起工作来让即将从可重复使用的组件构建的应用程序的创建几部分组成:
• 一个主机系统提供一个符合COM规范的运行时环境。
• 接口定义功能合同,组件实现接口。
• 服务器提供组件到系统,以及客户使用由组件提供的功能。
• 一个注册表跟踪,其中组件部署在本地和远程主机。
• 一个服务控制管理器是定位在本地和远程主机上的组件和连接服务器到客户端。
• 一个结构化存储协议,定义如何浏览主机的文件系统中的文件的内容。
启用跨主机和平台代码复用是中央的COM。可重复使用的接口的实现被命名为组件,一个组件对象,或者一个COM对象。一个组件实现一个或多个COM接口。
您可以通过设计的界面,你的库实现自定义一个COM库。库的消费者可以发现和使用其功能无磁带库的部署和实施细节的任何知识。
对象和接口
一个COM对象通过暴露其特征接口,这是成员函数的集合。一个COM接口定义了组件的预期行为和责任,它指定一个强类型的合同,提供一小部分相关的操作。COM组件之间的所有通信都通过接口出现,并且由组件提供的所有服务都是通过其接口暴露出来。呼叫者只能访问接口的成员函数。除非它在接口暴露的内部状态是不可用的调用者。
接口是强类型。每个接口都有自己独特的接口标识符,名为IID,这消除了可能与人类可读的名称发生冲突。该IID是全局唯一标识符(GUID),这是由开放软件基金会(OSF)分布式计算环境(DCE)中定义的相同通用唯一ID(UUID)。当你创建一个新的接口,你必须创建该接口的新标识。当呼叫者使用的接口,它必须使用的唯一标识符。这种明确标识通过消除命名冲突将导致运行时故障提高稳健性。
当你定义一个新的接口,你可以通过使用接口定义语言(IDL)建立接口定义。从这个接口定义,微软IDL编译器使用的界面,和源代码来处理远程过程调用应用程序生成使用头文件。由微软提供的IDL是基于简单的扩展,以DCE IDL,远程过程调用(RPC)的行业标准为基础的分布式计算。IDL是为接口设计的便利性的工具,而不是中央对COM互操作。有了IDL,你不需要手动创建的头文件的每个编程环境。欲了解更多信息,请参阅定义COM接口。
继承是在COM接口谨慎使用。COM支持接口继承只重用与底座接口相关的合同。COM不支持继承的选择性; 因此,如果一个接口从另一个继承,它包括所有的,基接口定义的功能。此外,接口只使用单继承,而不是多个继承,从基站接口获得的功能。
接口的实现
您无法自行创建一个COM接口的一个实例。相反,你创建一个实现接口的类的实例。在C ++中,一个COM接口被建模为一个抽象基类,这意味着该接口是只包含纯虚成员函数C ++类。A C ++库通过从一个或多个接口继承的成员函数签名,重写每个成员函数,并提供用于每个功能的实现实现COM对象。
你可以使用任何支持函数指针的概念,以实现COM接口的任何编程语言。例如,在C,一个接口是包含一个指向函数指针,一个用于接口中的每个方法的表的结构。
当你实现一个接口,你的类必须提供该接口的每个功能的实现。如果类没有工作的接口函数来完成,实现可以是单个return语句。
COM类是通过使用一类具有在文件系统中的特定部署,这对于Windows是一个DLL或EXE相关联的唯一的128位类ID(CLSID)标识。甲CLSID是GUID,这意味着没有其他类具有相同的CLSID。采用独特的类标识符可以防止类之间的名称冲突。例如,两个不同的供应商可以编写一个名为CSTACK类,但两个类有一个独特的CLSID,从而避免碰撞的可能性。
您可以通过使用获得新的CLSID CoCreateGuid功能或使用COM创作工具,如Visual Studio,在内部调用此函数。
所谓COM(Componet Object Model,组件对象模型),是一种说明如何建立可动态互变组件的规范,此规范提供了为保证能够互操作,客户和组件应遵循的一些二进制和网络标准。通过这种标准将可以在任意两个组件之间进行通信而不用考虑其所处的操作环境是否相同、使用的开发语言是否一致以及是否运行于同一台计算机。

https://blog.csdn.net/byxdaz/article/details/6595210

一、Com概念
在COM规范下将能够以高度灵活的编程手段来开发、维护应用程序。可以将一个单独的复杂程序划分为多个独立的模块进行开发,这里的每一个独立模块都是一个自给自足的组件,可以采取不同的开发语言去设计每一个组件。在运行时将这些组件通过接口组装起来以形成所需要的应用程序。构成应用程序的每一个组件都可以在不影响其他组件的前提下被升级。这里所说的组件是特指在二进制级别上进行集成和重用而能够被独立生产获得和配置的软件单元。COM规范所描述的即是如何编写组件,遵循COM标准的任何一个组件都是可以被用来组合成应用程序的。至于对组件采取的是何种编程语言则是无关紧要的,可以自由选取。作为一个真正意义上的组件,应具备如下特征:
  1) 实现了对开发语言的封装。
  2) 以二进制形式发布。
  3) 能够在不妨碍已有用户的情况下被升级。
  4) 在网络上的位置必须能够被透明的重新分配。
  这些特征使COM组件具有很好的可重用性,这种可重用性与DLL一样都是建立在二进制基础上的代码重用。但是COM在多个方面的表现均要比DLL的重用方式好的多。例如,在DLL中存在的函数重名问题、各编译器对C++函数名称修饰的不兼容问题、路径问题以及与可执行程序的依赖性问题等在COM中通过使用虚函数表、查找注册表等手段均被很好的解决。其实COM组件在发布形式上本身就包扩DLL,只不过通过制订复杂的COM规范,使COM本身的机制改变了重用的方法,能够以一种新的方法来利用DLL并克服DLL本身所固有的一些缺陷,从而实现了更高层次的重用。
(1)函数重名问题
DLL里是一个一个的函数,我们通过函数名来调用函数,那如果两个DLL里有重名的函数怎么办?
(2)各编译器对C++函数的名称修饰不兼容问题
对于C++函数,编译器要根据函数的参数信息为它生成修饰名,DLL库里存的就是这个修饰名,但是不同的编译器产生修饰的方法不一样,所以你在VC里编写的DLL在BC里就可以用不了。不过也可以用extern"C";来强调使用标准的C函数特性,关闭修饰功能,但这样也丧失了C++的重载多态性功能。
(3)路径问题
放在自己的目录下面,别人的程序就找不到,放在系统目录下,就可能有重名的问题。而真正的组件应该可以放在任何地方甚至可以不在本机,用户根本不需考虑这个问题。
(4)DLL与EXE的依赖问题
我们一般都是用隐式连接的方式,就是编程的时侯指明用什么DLL,这种方式很简单,它在编译时就把EXE与DLL绑在一起了。如果DLL发行了一个新版本,我们很有必要重新链接一次,因为DLL里面函数的地址可能已经发生了改变。DLL的缺点就是COM的优点。
二、COM相关的结构、接口
1)、CLSID
CLSID其实就是一个号码,或者说是一个16字节的数。观察注册表,在HKEY_CLASSES_ROOT\CLSID{…}主键下,LocalServer32(DLL组件使用InprocServer32) 中保存着程序路径名称。CLSID 的结构定义如下:
typedef struct _GUID {
DWORD Data1; // 随机数
WORD Data2; // 和时间相关
WORD Data3; // 和时间相关
BYTE Data4[8]; // 和网卡MAC相关
} GUID;

typedef GUID CLSID; // 组件ID
typedef GUID IID; // 接口ID
#define REFCLSID const CLSID &

// 常见的声明和赋值方法
CLSID CLSID_Excel ={0x00024500,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
struct __declspec(uuid(“00024500-0000-0000-C000-000000000046”))CLSID_Excel;
class DECLSPEC_UUID(“00024500-0000-0000-C000-000000000046”)CLSID_Excel;
// 注册表中的表示方法
{00024500-0000-0000-C000-000000000046}
2)、ProgID
每一个COM组件都需要指定一个CLSID,并且不能重名。它之所以使用16个字节,就是要从概率上保证重复是“不可能”的。但是,微软为了使用方便与记忆,也支持另一个字符串名称方式,叫 ProgID。由于 CLSID 和 ProgID 其实是一个概念的两个不同的表示形式,所以我们在程序中可以随便使用任何一种。下面介绍一下 CLSID 和 ProgID 之间的转换方法和相关的函数:

函数

功能说明

CLSIDFromProgID()、CLSIDFromProgIDEx()

由 ProgID 得到 CLSID。没什么好说的,你自己都可以写,查注册表贝

ProgIDFromCLSID()

由 CLSID 得到 ProgID,调用者使用完成后要释放 ProgID 的内存(注5)

CoCreateGuid()

随机生成一个 GUID

IsEqualGUID()、IsEqualCLSID()、IsEqualIID()

比较2个ID是否相等

StringFromCLSID()、StringFromGUID2()、StringFromIID()

由 CLSID,IID 得到注册表中CLSID样式的字符串,注意释放内存

3)、接口
3.1、函数是通过 VTAB 虚函数表提供其地址, 从另一个角度来看,不管用什么语言开发,编译器产生的代码都能生成这个表。这样就实现了组件的“二进制特性”轻松实现了组件的跨语言要求。
3.2、假设有一个指针型变量保存着 VTAB 的首地址,则这个变量就叫“接口指针, 变量命名的时候,习惯上加上"I"开头。另外为了区分不同的接口,每个接口 也都要有一个名字,该名字就和 CLSID 一样,使用 GUID 方式,叫 IID。
3.3、接口一经发表,就不能再修改了。不然就会出现向前兼容的问题。这个性质叫“接口不变性”。
3.4、组件中必须有3个函数,QueryInterface、AddRef、Release,它们3个函数也组成一个接口,叫"IUnknown"。
3.5、任何接口,其实都包含了 IUnknown 接口。随着你接触到更多的接口就会了更体会解到接口的另一个性质“继承性”。
3.6、在任何接口上,调用表中的第一个函数,其实就是调用 QueryInterface()函数,就得到你想要的另外一个接口指针。这个性质叫“接口的传递性”
3.7、C/C++语言中需要事先对函数声明,那么就 会要求组件也必须提供C语言的头文件。不行!为了能使COM具有跨语言的能力,决定不再为任何语言提供对应的函数接口声明,而是独立地提供一个叫类型库(TLB)的声明。每个语言的IDE环境自己去根据TLB生成自己语言需要的包装。这个性质叫“接口声明的独立性”。
4)COM组件数据类型
HRESULT 函数返回值
HRESULT Add( long n1, long n2, long *pSum)
{
*pSum = n1 + n2;
return S_OK;
}
  如果函数正常执行,则返回 S_OK,同时真正的函数运行结果则通过参数指针返回。如果遇到了异常情况,则COM系统经过判断,会返回相应的错误值。常见的返回值有:

HRESULT

含义

S_OK

0x00000000

成功

S_FALSE

0x00000001

函数成功执行完成,但返回时出现错误

E_INVALIDARG

0x80070057

参数有错误

E_OUTOFMEMORY

0x8007000E

内存申请错误

E_UNEXPECTED

0x8000FFFF

未知的异常

E_NOTIMPL

0x80004001

未实现功能

E_FAIL

0x80004005

没有详细说明的错误。一般需要取得 Rich Error 错误信息(注1)

E_POINTER

0x80004003

无效的指针

E_HANDLE

0x80070006

无效的句柄

E_ABORT

0x80004004

终止操作

E_ACCESSDENIED

0x80070005

访问被拒绝

E_NOINTERFACE

0x80004002

不支持接口

(图:HRESULT 的结构)
  HRESULT 其实是一个双字节的值,其最高位(bit)如果是0表示成功,1表示错误。具体参见 MSDN 之"Structureof COM Error Codes"说明。我们在程序中如果需要判断返回值,则可以使用比较运算符号;switch开关语句;也可以使用VC提供的宏:
HRESULT hr = 调用组件函数;
if( SUCCEEDED( hr ) ){…} // 如果成功

if( FAILED( hr ) ){…} // 如果失败

BSTR
  COM 中除了使用一些简单标准的数据类型外(注2),字符串类型需要特别重点地说明一下。还记得原则吗?COM 组件是运行在分布式环境中的。通俗地说,你不能直接把一个内存指针直接作为参数传递给COM函数。你想想,系统需要把这块内存的内容传递到“地球另一 边”的计算机上,因此,我至少需要知道你这块内存的尺寸吧?不然让我如何传递呀?传递多少字节呀?!而字符串又是非常常用的一种类型,因此 COM 设计者引入了 BASIC 中字符串类型的表示方式—BSTR。BSTR 其实是一个指针类型,它的内存结构是:(输入程序片段 BSTR p = ::SysAllocString(L"Hello,你好");断点执行,然后观察p的内存)

(图:BSTR 内存结构)、
  BSTR 是一个指向 UNICODE 字符串的指针,且 BSTR 向前的4个字节中,使用DWORD保存着这个字符串的字节长度( 没有含字符串的结束符)。
有关 BSTR 的处理函数:

API 函数

说明

SysAllocString()

申请一个 BSTR 指针,并初始化为一个字符串

SysFreeString()

释放 BSTR 内存

SysAllocStringLen()

申请一个指定字符长度的 BSTR 指针,并初始化为一个字符串

SysAllocStringByteLen()

申请一个指定字节长度的 BSTR 指针,并初始化为一个字符串

SysReAllocStringLen()

重新申请 BSTR 指针

CString 函数

说明

AllocSysString()

从 CString 得到 BSTR

SetSysString()

重新申请 BSTR 指针,并复制到 CString 中

CComBSTR 函数

ATL 的 BSTR 包装类。在 atlbase.h 中定义

Append()、AppendBSTR()、AppendBytes()、ArrayToBSTR()、BSTRToArray()、AssignBSTR()、Attach()、Detach()、Copy()、CopyTo()、Empty()、Length()、ByteLength()、ReadFromStream()、WriteToStream()、LoadString()、ToLower()、ToUpper() 运算符重载:!,!=,==,<,>,&,+=,+,=,BSTR

 太多了,但从函数名称不能看出其基本功能。详细资料,查看MSDN 吧。另外,左侧函数,有很多是 ATL 7.0 提供的,VC6.0 下所带的 ATL 3.0 不支持。由于我们将来主要用 ATL 开发组件程序,因此使用 ATL 的 CComBSTR 为主。VC也提供了其它的包装类 _bstr_t。

各种字符串类型之间的转换
函数 WideCharToMultiByte(),转换 UNICODE 到MBCS。使用范例:
LPCOLESTR lpw = L"Hello,你好";
size_t wLen = wcslen( lpw ) + 1; // 宽字符字符长度,+1表示包含字符串结束符

  int aLen=WideCharToMultiByte(  // 第一次调用,计算所需 MBCS 字符串字节长度CP_ACP,0,lpw,  // 宽字符串指针wLen, // 字符长度NULL,0,  // 参数0表示计算转换后的字符空间NULL,NULL);LPSTR lpa = new char [aLen];WideCharToMultiByte(CP_ACP,0,lpw,wLen,lpa,  // 转换后的字符串指针aLen, // 给出空间大小NULL,NULL);// 此时,lpa 中保存着转换后的 MBCS 字符串... ... ... ...delete [] lpa;函数 MultiByteToWideChar(),转换MBCS 到 UNICODE。使用范例:LPCSTR lpa = "Hello,你好";size_t aLen = strlen( lpa ) + 1;int wLen = MultiByteToWideChar(CP_ACP,0,lpa,aLen,NULL,0);LPOLESTR lpw = new WCHAR [wLen];MultiByteToWideChar(CP_ACP,0,lpa,aLen,lpw,wLen);... ... ... ...delete [] lpw;

使用 ATL 提供的转换宏。

A2BSTR

OLE2A

T2A

W2A

A2COLE

OLE2BSTR

T2BSTR

W2BSTR

A2CT

OLE2CA

T2CA

W2CA

A2CW

OLE2CT

T2COLE

W2COLE

A2OLE

OLE2CW

T2CW

W2CT

A2T

OLE2T

T2OLE

W2OLE

A2W

OLE2W

T2W

W2T

上表中的宏函数,其实非常容易记忆:

2

好搞笑的缩写,to 的发音和 2 一样,所以借用来表示“转换为、转换到”的含义。

A

ANSI 字符串,也就是 MBCS。

W、OLE

宽字符串,也就是 UNICODE。

T

中间类型T。如果定义了 _UNICODE,则T表示W;如果定义了 _MBCS,则T表示A

C

const 的缩写

使用范例:
#include<atlconv.h>
void fun()
{
USES_CONVERSION; // 只需要调用一次,就可以在函数中进行多次转换
LPCTSTR lp = OLE2CT( L"Hello,你好"));
… … … …
// 不用显式释放 lp 的内存,因为
// 由于 ATL 转换宏使用栈作为临时空间,函数结束后会自动释放栈空间。
}

VARIANT
  C++、BASIC、Java、Pascal、Script…计算机语言多种多样,而它们各自又都有自己的数据类型,COM 产生目的,其中之一就是要跨语言(注3)。而 VARIANT 数据类型就具有跨语言的特性,同时它可以表示(存储)任意类型的数据。从C语言的角度来讲,VARIANT 其实是一个结构,结构中用一个域(vt)表示------该变量到底表示的是什么类型数据,同时真正的数据则存贮在 union 空间中。结构的定义太长了(虽然长,但其实很简单)大家去看 MSDN 的描述吧,这里给出如何使用的简单示例:

学生:我想用 VARIANT 表示一个4字节长的整数,如何做?
老师:VARIANT v;v.vt=VT_I4; v.lVal=100;

学生:我想用 VARIANT 表示布尔值“真”,如何做?
老师:VARIANT v;v.vt=VT_BOOL; v.boolVal=VARIANT_TRUE;

在我们写程序的时候到比较简单,请大家遵守几个原则:
  1、启动组件得到一个接口指针(Interface)后,不要调用AddRef()。因为系统知道你得到了一个指针,所以它已经帮你调用了AddRef()函数;
  2、通过QueryInterface()得到另一个接口指针后,不要调用AddRef()。因为…和上面的道理一样;
  3、当你把接口指针赋值给(保存到)另一个变量中的时候,请调用AddRef();
  4、当不需要再使用接口指针的时候,务必执行Release()释放;
  5、当使用智能指针的时候,可以省略指针的维护工作;

内存分配和释放

C语言

C++语言

Windows 平台

COM

IMalloc 接口

BSTR

malloc()

new
GlobalAlloc()
CoTaskMemAlloc()

Alloc()

SysAllocString()

realloc()

GlobalReAlloc()

CoTaskRealloc()

Realloc()

SysReAllocString()

free()

delete

GlobalFree()

CoTaskMemFree()

Free()

SysFreeString()

以上这些函数必须要按类型配合使用(比如:new 申请的内存,则必须用delete 释放)。

三、VC进行COM编程
VC进行COM编程,必须要掌握哪些COM理论知识。要学COM的基本原理,我推荐的书是《COM技术内幕》。但仅看这样的书是远远不够的,我们最终的目的是要学会怎么用COM去编程序,而不是拼命的研究COM本身的机制。所以我个人觉得对COM的基本原理不需要花大量的时间去追根问底,没有必要,是吃力不讨好的事。其实我们只需要掌握几个关键概念就够了。这里用VC编程所必需掌握的几个关键概念。

  1. COM组件实际上是一个C++类,而接口都是纯虚类。组件从接口派生而来我们可以简单的用纯粹的C++的语法形式来描述COM是个什么东西:
    class IObject
    {
    public:
    virtual Function1(…) = 0;
    virtual Function2(…) = 0;

    };
    class MyObject : public IObject
    {
    public:
    virtual Function1(…){…}
    virtual Function2(…){…}

    };
    看清楚了吗?IObject就是我们常说的接口,MyObject就是所谓的COM组件。切记接口都纯虚类,它所包含的函数都是纯虚函数,而且它没有成员变量。而COM组件就是从这些纯虚类继承下来的派生类,它实现了这些虚函数,仅此而已。从上面也可以看出,COM组件是以C++为基础的,特别重要的是虚函数和多态性的概念,COM中所有函数都是虚函数,都必须通过虚函数表VTable来调用,这一点是无比重要的,必需时刻牢记在心。
  2. COM组件有三个最基本的接口类,分别是IUnknown、IClassFactory、IDispatchCOM规范规定任何组件、任何接口都必须从IUnknown继承,IUnknown包含三个函数,分别是QueryInterface、AddRef、Release。这三个函数是无比重要的,而且它们的排列顺序也是不可改变的。QueryInterface用于查询组件实现的其它接口,说白了也就是看看这个组件的父类中还有哪些接口类,AddRef用于增加引用计数,Release用于减少引用计数。引用计数也是COM中的一个非常重要的概念。大体上简单的说来可以这么理解,COM 组件是个DLL,当客户程序要用它时就要把它装到内存里。
    另一方面,一个组件也不是只给你一个人用的,可能会有很多个程序同时都要用到它。但实际上DLL只装载了一次,即内存中只有一个COM组件,那COM组件由谁来释放?由客户程序吗?不可能,因为如果你释放了组件,那别人怎么用,所以只能由COM组件自己来负责。所以出现了引用计数的概念,COM维持一个计数,记录当前有多少人在用它,每多一次调用计数就加一,少一个客户用它就减一,当最后一个客户释放它的时侯,COM知道已经没有人用它了,它的使用已经结束了,那它就把它自己给释放了。
    引用计数是COM编程里非常容易出错的一个地方,但所幸VC的各种各种的类库里已经基本上把AddRef的调用给隐含了,在我的印象里,我编程的时侯还从来没有调用过AddRef,我们只需在适当的时侯调用Release。至少有两个时侯要记住调用Release,第一个是调用了QueryInterface以后,第二个是调用了任何得到一个接口的指针的函数以后,记住多查MSDN以确定某个函数内部是否调用了AddRef,如果是的话那调用Release的责任就要归你了。
    IUnknown的这三个函数的实现非常规范但也非常烦琐,容易出错,所幸的事我们可能永远也不需要自己来实现它们。
    IClassFactory的作用是创建COM组件。我们已经知道COM组件实际上就是一个类,那我们平常是怎么实例化一个类对象的?是用‘new’命令!很简单吧,COM组件也一样如此。但是谁来new它呢?不可能是客户程序,因为客户程序不可能知道组件的类名字,如果客户知道组件的类名字那组件的可重用性就要打个大大的折扣了,事实上客户程序只不过知道一个代表着组件的128位的数字串而已,这个等会再介绍。所以客户无法自己创建组件,而且考虑一下,如果组件是在远程的机器上,你还能new出一个对象吗?所以创建组件的责任交给了一个单独的对象,这个对象就是类厂。
    每个组件都必须有一个与之相关的类厂,这个类厂知道怎么样创建组件,当客户请求一个组件对象的实例时,实际上这个请求交给了类厂,由类厂创建组件实例,然后把实例指针交给客户程序。这个过程在跨进程及远程创建组件时特别有用,因为这时就不是一个简单的new操作就可以的了,它必须要经过调度,而这些复杂的操作都交给类厂对象去做了。
    IClassFactory最重要的一个函数就是CreateInstance,顾名思议就是创建组件实例,一般情况下我们不会直接调用它,API函数都为我们封装好它了,只有某些特殊情况下才会由我们自己来调用它,这也是VC编写COM组件的好处,使我们有了更多的控制机会,而VB给我们这样的机会则是太少太少了。
    IDispatch叫做调度接口。它的作用何在呢?这个世上除了C++还有很多别的语言,比如VB、VJ、VBScript、JavaScript等等。可以这么说,如果这世上没有这么多乱七八糟的语言,那就不会有IDispatch。

    COM(Componet Object Model_组件对象模型)技术概述相关推荐

    1. OLE技术及组件对象模型(COM)

      1.OLE技术 Object Linking and Embedding,对象连接与嵌入,简称OLE技术.OLE 不仅是桌面应用程序集成,而且还定义和实现了一种允许应用程序作为软件"对象&q ...

    2. 【VS开发】COM组件技术概述

      这篇文章对COM做出来比较完整的解释,非常好. COM是微软公司为了计算机工业的软件生产更加符合人类的行为方式开发的一种新的软件开发技术.在COM构架下,人们可以开发出各种各样功能专一的组件,然后将它 ...

    3. web前端主要技术概述

      web前端主要技术概述 参考资料: 2018 Web 开发者路线图 2017年前端框架.类库.工具大比拼 本文主要是介绍部分主流和新兴的web前端技术,希望能帮助想学web前端的小白,理清其技术学习路 ...

    4. 打印机连接技术概述(LPRRAWAppleTalk)

      简介 网络打印连接在两个方面对Microsoft Windows打印服务器的性能和可扩展性产生重大影响.首先,了解可用于将客户工作站连接到打印服务器的选择很重要.此外,用于将服务器上的作业发送到实际打 ...

    5. Internet Information Services 5.0 技术概述(转)

      Internet Information Services 5.0 技术概述 操作系统 白皮书 摘要 本白皮书为信息技术专业人员,提供随 Microsoft Windows 2000 提供的 Inte ...

    6. COM, OLE技术概述

      COM             COM即组件对象模型,是一种以组件为发布单元的对象模型,这种模型使各软件组件可以用一种统一的方式进行交互 .在COM标准中,一个组件程序也被称为一个模块,它可以是一个动 ...

    7. 组件对象模型:COM

      一.组件 (com),是微软公司为了计算机工业的软件生产更加符合人类的行为方式开发的一种新的软件开发技术.在com构架下,人们可以开发出各种各样的功能专一的组件,然后将它们按照需要组合起来,构成复杂的 ...

    8. (转)Eclipse平台技术概述

      转载:周金根 http://zhoujg.blog.51cto.com/1281471/516833  Eclipse:Eclipse平台技术概述 2010-10-19 13:35:00 标签:Ecl ...

    9. 系统接口规范以及常见的接口技术概述和比较

      系统接口规范以及常见的接口技术概述和比较 一.基本要求: 为了保证系统的完整性和健壮性,系统接口应满足下列基本要求: 1.接口应实现对外部系统的接入提供企业级的支持,在系统的高并发和大容量的基础上提供 ...

    最新文章

    1. 如何让AI教机器自己玩俄罗斯方块?
    2. 10-20国际标准导联系统
    3. small用于不连续数组_用Small、If、Index、Indirect、Row、Char、Match实现一对多查找...
    4. ajax中json和文本的区别,json格式字符串--json对象 【ajax_responseText】重点
    5. python 字典 get(),items(),iteritems()方法
    6. C++ 中复杂的声明
    7. outlook附件大小限制_如何在Outlook中调整大图片附件的大小
    8. 11.企业应用架构模式 --- 对象-关系行为模式
    9. Spring Boot和Dubbo整合
    10. linux 读写信号量学习
    11. 关于dsoframer VC++下的使用
    12. 微信小程序腾讯云实时语音转写
    13. 微信小游戏上线发布全流程详解
    14. 如何用CSS把正方形变成圆形
    15. table表格及属性
    16. curl 请求日志_CURL常用命令
    17. AI的10个开源工具/框架
    18. 【Anaconda】修改conda默认envs_dirs和pkgs_dirs
    19. 用PhoneGap开发移动程序
    20. VMware Workstation 在此主机上不支持嵌套虚拟化。模块“HV”启动失败。未能启动虚拟机。

    热门文章

    1. LIKE语句通配符:%|_|[]
    2. Tensorflow White Paper(一)
    3. 第二章:低功耗器件选型:负载开关 loadswitch
    4. 大鱼号自媒体原创视频好过吗,大鱼号自媒体原创视频收益怎么样
    5. 小米手机解BL锁时 进入fastboot之后 PC端手机解锁工具一直显示未连接手机
    6. 软件测试工程师在线培训,软件测试工程师培训.PDF
    7. 安装Android应用至SD卡
    8. 分布式事务、基于Best Efforts 1PC模式的事务
    9. 管理跨国虚拟团队的技巧
    10. 红芯商业计划书曝光:明年要实现3000万利润 2021年冲刺IPO