COM的一些基本概念
2016-06-28 17:13
357 查看
Windows lets you share code at the binary level using DLLs. After all, that's how Windows apps function - reusing kernel32.dll, user32.dll, etc. But since the DLLs are written to a C interface, they can only be used by C or languages that understand the C calling convention. This puts the burden of sharing on the programming language implementer, instead of on the DLL itself.
MFC introduced another binary sharing mechanism with MFC extension DLLs. But these are even more restrictive - you can only use them from an MFC app.
COM solves all these problems by defining a binary standard, meaning that COM specifies that the binary modules (the DLLs and EXEs) must be compiled to match a specific structure. The standard also specifies exactly how COM objects must be organized in memory. The binaries must also not depend on any feature of any programming language (such as name decoration in C++). Once that's done, the modules can be accessed easily from any programming language. A binary standard puts the burden of compatibility on the compiler that produces the binaries, which makes it much easier for the folks who come along later and need to use those binaries.
A coclass (short for component object class) is contained in a DLL or EXE, and contains the code behind one or more interfaces. The coclass is said to implement those interfaces. A COM object is an instance of a coclass in memory. Note that a COM "class" is not the same as a C++ "class", although it is often the case that the implementation of a COM class is a C++ class.
A class ID, or CLSID, is a GUID that names a coclass. An interface ID, or IID, is a GUID that names an interface.
An HRESULT is an integral type used by COM to return error and success codes. It is not a "handle" to anything, despite the H prefix. I'll have more to say about HRESULTs and how to test them later on.
The COM library is the part of the OS that you interact with when doing COM-related stuff. Often, the COM library is referred to as just "COM,"
Every language has its own way of dealing with objects. For example, in C++ you create them on the stack, or use new to dynamically allocate them. Since COM must be language-neutral, the COM library provides its own object-management routines. A comparison of COM and C++ object management is listed below:
Creating a new object
In C++, use operator new or create an object on the stack.
In COM, call an API in the COM library.
Deleting objects
In C++, use operator delete or let a stack object go out of scope.
In COM, all objects keep their own reference counts. The caller must tell the object when the caller is done using the object. COM objects free themselves from memory when the reference count reaches 0.
Now, in between those two stages of creating and destroying the object, you actually have to use it. When you create a COM object, you tell the COM library what interface you need. If the object is created successfully, the COM library returns a pointer to the requested interface. You can then call methods through that pointer, just as if it were a pointer to a regular C++ object.
Handling HRESULTs
I've already shown some simple error handling, using the SUCCEEDED and FAILED macros. Now I'll give some more details on what to do with the HRESULTs returned from COM methods.An HRESULT is a 32-bit signed integer, with nonnegative values indicating success, and negative values indicating failure. An HRESULT has three fields: the severity bit (to indicate success or failure), the facility code, and the status code. The "facility" indicates what component or program the HRESULT is coming from. Microsoft assigns facility codes to the various components, for example COM has one, the Task Scheduler has one, and so on. The "code" is a 16-bit field that has no intrinsic meaning; the codes are just an arbitrary association between a number and a meaning, just like the values returned by GetLastError().
If you look up error codes in the winerror.h file, you'll see a lot of HRESULTs listed, with the naming convention [facility]_[severity]_[description]. Generic HRESULTs that can be returned by any component (likeE_OUTOFMEMORY) have no facility in their name. Examples:
REGDB_E_READREGDB: Facility = REGDB, for "registry database"; E = error; READREGDB is a description of the error (couldn't read the database).
S_OK: Facility = generic; S = success; OK is a description of the status (everything's OK).
Fortunately, there are easier ways to determine the meaning of an HRESULT than looking through winerror.h.HRESULTs for built-in facilities can be looked up with the Error Lookup tool. For example, say you forgot to callCoInitialize() before CoCreateInstance(). CoCreateInstance() will return a value of 0x800401F0. You can enter that value into Error Lookup and you'll see the description: "CoInitialize has not been called."
You can also look up HRESULT descriptions in the debugger. If you have an HRESULT variable called hres, you can view the description in the Watch window by entering "hres,hr" as the value to watch. The ",hr" tells VC to display the value as an HRESULT description.
相关文章推荐
- [改善Java代码]强制声明泛型的实际类型
- 【Leetcode】92. Reverse Linked List II && 206. Reverse Linked List
- 开源大数据查询分析引擎现状
- 行为驱动开发Cucumber的目录结构和执行过程
- Java开发中的23种设计模式详解
- HDFS中的文件许可
- cocoapods的简单安装和使用
- java中常用的设计模式
- RUMBA+LCD12864(RepRapDiscount_Full_Graphic_Smart_Controller)
- http url转义字符,特殊字符
- ReactiveCocoa框架菜鸟入门(三)——信号(Signal)与订阅者(Subscriber)
- Reach vs. HiDef
- 学习Javascript闭包(Closure)
- iOS开发tableview二级联动的细节实现中注意的细节总结
- [改善Java代码]不能初始化泛型参数和数组
- Oracle 添加第二个实例 和 监听
- openstack-networking-neutron(一)---端到端和点到点的理解
- [原]JointJS流程图
- 可视化时钟,好吧!我承认我懒
- Codeforces Round #359 (Div. 2)