COM technology Overview

Source: Internet
Author: User
COM technology Overview

-- Tsingxiao

I. Overview

Since its birth, PC hardware has undergone numerous changes. From the initial intel 8086 CPU to the present, piII is only
More than 10 years. Microsoft's Windows operating system has been installed on the desktop system since the first version of 1.0 and is about to launch Win2000.
The largest OS. As a software developer, we use Visual Basic, Visual C ++, and Delphi includes the latest
Borland C ++ builder and many other development environments develop applications for Windows. It should be said that the current development conditions and
A year ago, it was a great improvement.

If you have developed a 16-bit windows program, you may know that in order to read a file, we have to use a small assembly to call
Use a DOS routine, or use a function that is not made public by windows at the time: _ lopen (). In the Win32 environment, all you have to do is
Call: createfile () to obtain a file handle. Of course, if you use something like MFC or owl, you can simply
. But in general, programmers still have to write every line of code for the application from the beginning.

However, this situation has changed: Microsoft proposed the c o m (component object model, which can also be translated as "component pair
"Image model"), and is more and more widely used in the latest Windows 95/98 and Windows NT4: we have reason to believe that
In the near future, c o m will become the most common method for building applications. If you are interested in this technology, please refer to this article.
You can learn what you want to know. If you are already a c o m veteran, you are also welcome to criticize and correct, my email is singxiao@bigfoot.com

This article is intended for C ++ programmers. When introducing concepts, I try not to mix Win32 API knowledge so that you can
The essence of c o m is clearer. All examples are compiled using Microsoft Visual C ++ 5 (SP3.

Generally, an application is always composed of a single binary file. In the past, if this program needs to be improved
You need to modify the source code, compile it, claim the new file, and replace the original file. Now, let's look at the question from a completely new perspective.
Question: It can be different to split the entire EXE executable file, but the parts are relatively independent.
Software. After a program is released in the future, if you realize that you need to modify it, you only need to replace the problematic or necessary
You can set up the upgrade. You can even replace the components without affecting the normal operation of the program. If you are familiar
For Windows programming, you may think that DLL is what you call dynamic connection. In fact, COM is fully utilized.
The flexibility of Win32 dll can be implemented on Windows.

What are the advantages of doing so? First, users generally want to customize the applications they use, and the component technology is essentially
Therefore, users can replace the original one with a component that better meets their needs. Secondly, because the components are relative
With the independent components of the program, we can use the same component in different programs without any problems. the reusability of the software will
Greatly enhanced. Third, with the increase of network bandwidth and its importance, distributed network applications have undoubtedly become software markets.
More and more important purchase points on the market. The component price structure simplifies the process of developing such applications.

So what is com? It is a specification that describes how to establish dynamically changeable components. It defines some
Operation: the customer (a term that refers to a program that requires a certain component) must follow the standard. The com standard is a set of component architectures.
Set standard document format specifications. Com is published in the format of Win32 dynamic link library (DLL) or executable file (exe ).
Form of executable code.

COM components are dynamically connected, and COM components are completely language-independent. At the same time, COM components can be released in binary form.
The COM component can be upgraded to a new version without interfering with old customers.

You can now think that some services provided by com are similar to classes in C ++. However, the class is based on the source code, and the COM is not. No
Here I want to clarify some incorrect ideas about com: first, COM is not a computer language. Use com with a computer language (for example
C ++, VB) is meaningless. Second, do not compare the DLL with COM, because the COM technology uses the dynamic
The link capability can be achieved, but now the general point of view is that the best way to use DLL dynamic link capability is com. Of course, com
It is not a function set like Win32 API: it does not support or provides functions like movewindow to perform
Specific operation. Com is not a C ++ class library similar to MFC. Com is a language-independent group for developers.
But COM does not provide any implementation. To a certain extent, we can think that com is irrelevant to the system, and Software AG
The Organization is developing a series of COM support systems and is expected to operate from Mac OS, VMS, SCO UNIX to Linux in the near future.
The system will be able to implement COM. COM does have some specific implementations. Com itself needs to implement a library called com Library
API, which provides a series of services such as the customer's query of components and the registration/anti-Registration of components. Generally, the com library is operated by
Developers do not have to worry about the details of their implementations. In general, com provides a standard method for writing components. Follow com
Standard components can be combined to form applications. The implementation of these components is not important. Components
Contact the customer through the "interface.

Ii. What is an interface?

As mentioned above, the only way for COM components to deal with customers is through interfaces. In the implementation of C ++
Define the interface using the basic class, and then implement the component using multiple inheritance of the C ++ class. The following is a simple example:

////////////////
// Iface. h
////////////////

# Ifndef iface_h
# Define iface_h 1

# Define interface class

Interface IA
{
Public:
Virtual func1 () = 0;
Virtual func2 () = 0;
};

Interface IB
{
Public:
Virtual func3 () = 0;
Virtual func4 () = 0;
};

# Endif

/// // -- Iface. h end --//////

////////////////
// Test. c
////////////////

# Include "iface. H"

Class CA: Public IA, IB
{
Public:
CA (int I): m_count (I ){}
Virtual func1 () {cout <"IA: func1 is" <m_count * 1 <Endl;} virtual func2 () {cout <"IA :: func2 is "<m_count * 2 <Endl;} virtual func3 () {cout <" IB: func3 is "<m_count * 3 <Endl ;} virtual func4 () {cout <"IB: func4 is" <m_count * 4 <Endl ;}int m_count ;}; main () {Ia * PIA; IB * PIB; Ca * PCA = "new" Ca (2); Pia = "PCA;" Pia> func1 ();
Pia-> func2 ();
PIB-> func3 ();
PIB-> func4 ();
Delete PCA;
}

/// // -- Test. C end --//////

In the preceding example, the IA and IB interfaces are defined. You can note that all their member functions are declared as virtual and
End with = 0. Such functions are called pure virtual functions in C ++. If the entire class is composed of pure virtual functions
Is called the abstract base class. The abstract base class itself does not allocate memory because it does not have entity functions and variables. Generally
The purpose is to specify the memory structure for the derived class. For example, it is like dividing a house into many small rooms and specifying which small rooms should
What to put (the entity of the function), but the specific things should be filled in by the derived class.

Here is a concept that needs to be explained: components are not classes. We use a class to implement two sets of interfaces.
You can use it to implement more interfaces. A component is actually a set of interfaces and their implementations. A component may contain multiple interfaces.
Each interface has its own implementation. At the same time, interfaces are not always inherited. The COM specification does not require classes that implement an interface.
It must be inherited from that interface. This is because the customer does not understand the inheritance relationship of COM components. The inheritance of interfaces is only an implementation detail.
.

The QueryInterface function is described below. This function is used to query other interfaces. The customer communicates with components through
Interface. Even when the customer queries another component, it also needs to use an interface (in other words, if one component does not support
This interface is definitely not a COM component. The interface is named iunknown and has three functions, as shown below:

Interface iunknown
{
Virtual hresult _ stdcall QueryInterface (const IID & IID, void ** GMM) = 0;
Virtual ulong _ stdcall addref () = 0;
Virtual ulong _ stdcall release () = 0;
};

All interfaces of the COM component inherit iunknown, so that the first three functions of each interface are QueryInterface,
This means that all com interfaces can be processed as iunknown. You only need to use a cocreateinstance Function
You can create an instance for this component and obtain its iunknown *.

Hresult _ stdcall cocreateinstance (
Const CLSID & CLSID,
Iunknown * piunknownouter,
DWORD dwclscontext,
Const IID & IID,
Void **
);
The following code creates a component:

Extern "C" const guid clsid_com1 = (
0x32bb8230, 0xb41b1 0x11cf, 0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82 );

Extern "C" const guid iid_ix = (
0x32bb8230, 0xb591c 0x11ff, 0xc1, 0xb0, 0xc7, 0xf8, 0x21, 0x35, 0x1c, 0x2f );

Coinitialize ();

Ia * pix = NULL;
Hresult hR =: cocreateinstance (
Clsid_com1,
Null,
Clsctx_inproc_server,
Iid_ix,
(Void **) & pix
);

If (succeeded (HR ))
{
PIX-> FX ();
PIX-> release ();
}

Extern "C" const GUID is actually the so-called "globally unique identifier" (globally unique identifier ). We use
It represents different interfaces. In other words, if you find that two guids are identical, you have reason to believe that they indicate the same guid.
Interface. (There are dedicated algorithms to generate this structure, so that it is unique in time and space .) The following coinitialize Function
Initialize the com library. This step is very important. If Initialization is not performed, all subsequent operations will fail.

Next let's take a look at the hresult value. This is a 32-bit return value. Its highest bit indicates whether the function call is successful. 16th-bit inclusion
Is the return value of the function. The remaining 15 characters contain more detailed information about the type and origin of the returned value. To determine whether a function call is successful
Succeed and failed macros are required.

The cocreateinstance function is provided by the COM function library and is used to search for it in the system based on the queried components and interfaces.
File (usually an EXE or DLL file), create the component and query its interface. In general, the specific implementation of this function is
System-related, as will be mentioned later, in windows, the Registry will be queried to determine which file a specific component is located. Upper
For example, we query the clsid_com1 component. Since a component may contain multiple interfaces, we use iid_ix to specify the required
Interface, clsctx_inproc_server is a constant, and its specified component is a DLL (because the DLL runs in the customer's memory space,
So it can be called an in-process component ). The last parameter is an interface pointer, which returns the queried interface pointer. You can imagine,
A component pointer may be used by several customers at the same time. Therefore, a method is required to let the component instance know that it is being used by several customers,
In this way, he can destroy himself at an appropriate time to let out the memory space. If the actual destruction is inappropriate, for example, a pointer is being used
Future calls to this pointer will fail and the user program will crash. Com uses a relatively simple method for reference counting: dimension
Protects the global variables of a component or interface. If the value of this variable is zero, the time to destroy itself is reached. Cocreateinstance actually produces
The instance of this component is generated, and the reference count is set to 1 by calling the addref () function of iunknown internally. Because of this, the end of the example
The call of the release () function is to clean up: this interface pointer has completed its work, so the call of release () tells it:
Subtract one from your reference count. If this is not done, the component will always be kept in the memory until the application ends, and will not be cleared from the stack.
The addref and release functions are called to better control the life cycle of components. Of course, if properly handled, you can reduce the number
Addref/release to improve performance. A special case is that when the life cycle of a component is completely included in another component,
We do not count the included component. I am not going to discuss optimization issues in detail, because for general applications
Strong and stable is the most important thing. Progid is also introduced here. Progid is the easy-to-remember name specified by the programmer for a CLSID. Some
For example, Visual Basic uses progid rather than CLSID to represent components. Note that the naming of progid by programmers only follows
A conventional rule does not have any mandatory standards for specific implementation, so it is also possible for its name to conflict. Generally
Progid has the following format :..
Take my registry as an example:
Inshandler. inshandler.1
Imgutil. cosniffstream.1
Staticmetafile
Netscape. help.1
However, because progid does not have a special naming rule, it is entirely possible to have a name different from the above format. Sometimes the customer
Regardless of the version of the component it is connected to, in other words, the customer just needs to know that the component exists and is satisfied. Therefore, components often have
A version-independent progid, Which is mapped to the latest version of the installed component. Converts progid to clsid.
It is very simple. You only need to use the clsidfromprogid and progidfromclsid functions provided in the com library.
CLSID;
Clsidfromprogid (L "Netscape. help.1", & CLSID );
The above L "" is an expansion macro used to convert normal ANSI strings into Unicode strings.

The question to be discussed below is: If I have already written a component, how can I register its interface in the registry? Non
It is often simple. We only need to implement the following two functions in the component.
_ Declspec (dllexport) dllregisterserver ();
_ Declspec (dllexport) dllunregisterserver ();
Specifically, the implementation of dllregisterserver is actually achieved by directly calling the registry function. To register or cancel
Component registration. The following functions are generally used:
Regopenkeyex
Regcreatekeyex
Regsetvalueex
Regenumkeyex
Regdeletekey
Regclosekey
To use these functions, # include or, and add advapi32.lib to additional librarys. One question now
Question: How do customers choose the components they need? Developers need to know whether a component instance can be created without creating a component instance.
Provides the required interface methods. Polling all the components and interfaces in the system is a solution, but the overhead of the system is equivalent.
Large. To this end, a solution called component category is introduced.
A component category is actually an interface set. A guid is assigned to this set and uniquely identifies it. It is called
Catid. For any component, if it implements all interfaces of a component category, it can register itself
A member of the component category. In this way, you only need to select the appropriate component category and query all the components listed under it.
A component does not have to belong to only one component category. In turn, components belonging to a certain component category are not limited to only implementing changes
Interface in the component category. If you are happy, you can write a component that supports all component levels and has additional interfaces. Component class
How is it implemented? Use component category Manager (provided by Windows), which is an implementation
The components of the icatregister and icatinformation interfaces. Icatregister can complete the registration or cancellation of the new component category.
You can register or cancel a component. Icatinformation can be used to obtain a component class in the system.
Other data.
The component allocates a piece of memory and passes it to the customer through a parameter (possibly a returned pointer ).
A very common practice. Q: Who will release the memory? This is mainly because the formation and the customer may have different programmers.
There is no way between them to establish a standard way to allocate and release memory. The solution to each problem in COM is to provide
Interface (imalloc), which can be returned by cogetmalloc. To allocate memory, you only need to call imalloc: alloc and call
The memory allocated by the function can be imalloc: free for release. For easier implementation, the com Library provides two
Simple functions:
Void cotaskmemalloc (ulong CB/* size in bytes of block to be allocated */);
Void cotaskmemfree (void * PV );

If you read my article carefully, you have a general concept so far: What is com,
To which extent does it need to be implemented by programmers and which are completed by the COM library provided by the operating system. Not strictly speaking,
The purpose of COM is to classify various functions and encapsulate them into objects in Windows using DLL or
The format of EXE exists, and through the registry, window can know that the code of a specific component is
DLL or EXE. How can I tell windows which component do you need? We use guid to ensure the security of complex algorithms.
It proves that the IDs of no two interfaces in the world are exactly the same! This allows you to uniquely determine components, including included interfaces,
When the customer needs this component, Windows can load it correctly. It is also because of this uniqueness that the customer
You can always go straight and ask windows without error. What I want is this interface in this component! Tell me you have
? At this time, through a cocreateinstance function, Windows will return the interface pointer, or simply tell you that no
Find! So what did windows do when executing this function? First, it queries the Registry to find you
The component (component is the interface set, and the so-called interface is synonymous with the set composed of a group of functions, so you understand
?) If this component is not found, the query will naturally fail and the function will return. If this component is found, the kernel will
Windows returns the iunknown * pointer of this component. Windows then uses the iunknown: QueryInterface function to query your
Whether or not the specified interface is implemented (or supported) by this component, you can find that all interfaces generally come from
It is always implemented by your code. iunknown is an interface that must be implemented by all COM components. One of its purposes is
Windows knows how to query your components. Until only you implement the interfaces in the component-the person who writes the component
You have the responsibility to properly perform some QueryInterface functions to return the correct pointer. Windows then transfers the pointer
The whole process ends when cocreateinstance is called. Do you understand it now?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.