The COM component has three basic interface classes: iunknown, iclassfactory, and idispatch.
The COM specification specifies that all components and interfaces must be inherited from iunknown. iunknown contains three functions: QueryInterface, addref, and release. These three functions are extremely important, and their order cannot be changed. QueryInterface is used to query other interfaces implemented by the component. To put it bluntly, it is used to check which interface classes exist in the parent class of the component. addref is used to increase the reference count, and release is used to reduce the reference count. Reference counting is also a very important concept in COM. In general, it can be understood that the COM component is a DLL, and it should be loaded into the memory when the client program uses it. On the other hand, a component is not only for you, but may be used by many programs at the same time. But in fact, the DLL is only loaded once, that is, there is only one COM component in the memory. Who will release the COM component? Is it a client program? No, because if you release components, how can they be used by others? Therefore, the COM component is only responsible for this. Therefore, the concept of reference count emerged. com maintains a count and records the number of people currently using it. Each time multiple calls are called, the count is incremented. If one customer uses it, the count is reduced by one, when the last customer releases it, com knows that no one has used it, and its use is over, then it releases it. Reference counting is a very error-prone place in COM programming, but fortunately, the various class libraries of VC have basically implicitly called addref. In my impression, I have never called addref during programming. We only need to call release at the appropriate time. Remember to call release at least two times. The first is to call QueryInterface, and the second is to call any function that gets a pointer to an interface, remember to check msdn to check whether addref is called in a function. If so, you will be responsible for calling release. The implementation of the three functions of iunknown is very standard but cumbersome and error-prone. Fortunately, we may never need to implement them ourselves.
Iclassfactory is used to create COM components. We already know that the COM component is actually a class. How do we instantiate a class object? Use the 'new' command! It's easy, as is the COM component. But who will come to new it? It cannot be a customer program, because the customer program cannot know the class name of the component. If the customer knows the Class Name of the component, the reusability of the component will be greatly reduced, in fact, the customer program only knows a 128-bit numeric string representing the component, which will be introduced later. Therefore, you cannot create components on your own. If the components are on a remote machine, can you create a new object? Therefore, the responsibility for creating components is assigned to a separate object, which is a class factory. Each component must have a relevant class factory. This class factory knows how to create a component. When the customer requests an instance of a component object, the request is actually sent to the class factory, the class factory creates a component instance and then delivers the instance pointer to the customer program. This process is particularly useful when creating components across processes and remotely, because it is not a simple new operation, and it must be scheduled, these complex operations are handed over to the class factory objects. The most important function of iclassfactory is createinstance. The component is to create a component instance. Generally, we will not directly call it. The API function encapsulates it for us, only in some special circumstances can we call it by ourselves. This is also the advantage of VC's compilation of COM components, giving us more control opportunities, however, VB has given us too few and too few opportunities.
Idispatch is called a scheduling interface. What is its role? In addition to C ++, there are many other languages, such as VB, VJ, VBScript, and JavaScript. It can be said that if there are not so many messy languages in the world, there will be no idispatch. :-) We know that the COM component is a C ++ class and uses a virtual function table to call functions. For VC, there is no problem. This was originally designed for C ++, in the past, VB did not work. Now VB can use pointers, or vtable to call functions. VJ also works, but some languages still do not work, that is, the script language, typical examples include VBScript and JavaScript. The reason is that they do not support pointers. How can they use polymorphism and call these virtual functions even if pointers cannot be used. Alas, there is no way to ignore these scripting languages. Currently, all these scripting languages are used on the webpage, and distributed applications are also a major market for COM components, it has to be called by these script languages. Since the virtual function table method does not work, we can only find another method. As a hero, idispatch came into being. :-) The scheduling interface records every attribute of a function. When the client program calls these function attributes, it just sends these numbers to the idispatch interface, idispatch then calls the corresponding function based on these numbers. Of course, the actual process is far more complex than this. Simply giving a number will let others know how to call a function. Isn't it a great night? You have to let others know what parameters are required for the function to be called, what are the parameter types and what are returned? It is a headache to handle these problems in a unified way. The main function of the idispatch interface is invoke, which is called by the client program, and then invoke calls the corresponding function, if you look at the code that implements invoke in the MS class library, you will be amazed at the complexity of its implementation, because you have to consider various parameter types. Fortunately, we don't need to do it ourselves, and there may never be such an opportunity. :-)