1. How many years of software development processes have not changed, and the main problems need to face during software development, such as: long development cycle, difficult to ensure the correctness of the program, it is difficult to maintain, etc. Good solution, despite the concepts and tools such as object-oriented, frame design, etc. The component object model is an expansion of the traditional object-oriented model. The focus of traditional object-oriented models is the source program, as well as system analysis and design processes. The concept of components emphasizes how large software systems consist of small executable components of different developers. The following is first started from the object-oriented model. · Object-oriented programming is a long-awaited concept with the majority of programmers and industries. Object-oriented programming language allows developers to write programs in accordance with the model of people thinking about people in the real world, which allows developers to better express the objects existing in real realism, so that the development code is simple and easy to maintain. Object-oriented language has the following three most important concepts: Encapsulation - emphasizing the implementation details of the hidden object, and the user's user uses the object only by defining the object. Inheritance - new objects can utilize the functions of old objects. Polymorphism - A variety of different behaviors are displayed based on the objects used. From the overall view of the program, the most important concept for object-oriented programming to the user is the sharing and reuse of the code, which is extremely important for improving the efficiency of the writing program. However, the sharing and reuse of code still exists in practice, such as the upgrade of the version, the change in the interface, sharing code between different programming languages, and so on. There is no corresponding answer for these difficult object-oriented programming methods, which is the background of the component object model. • Component object models Decompose engineering into logical components is the basis for component analysis and design, which is the basis of component software. The component software system consists of a reusable binary software component module, and only a quite small change can be combined with the component modules from different developers. It is particularly important that such a combination does not require source code, and does not need to be recompiled. The components are communicating based on binary specifications, which is called binary reuse. The component module is independent of the programming language, and there is no definition from each other in addition to the standard method between the client programs and components. Components can be divided into different types, including visual components such as buttons or list boxes; feature components such as printing or spelling checks. For example, a component-based architecture can provide a mechanism in inserting multiple developers's spell check components into another developer's word processing application so that users can easily select and replace the word processing software according to their own preferences. The most important concept in the component structure is the interface. The interface is a collection of related methods in the same name (usually a unique ID value). Communication between components is based on an interface, and the interface is a contract with a strict type of components and their customers. Two objects that implement the same interface are considered to be polymorphic, and the polymorphisms here do not include the meaning of the base class pointer to the derived object, which means that the same interface can be implemented by multiple objects. 2. Basic concepts of COM / DCOM · Overview: The basic concepts of COM / DCOM will be explained below by program instance. Based on Microsoft's consistent style, although COM / DCOM claims to be a cross-platform support heterogeneous model (also indeed fundamentally across platform), it is also closely combined with other concepts in the Microsoft Windows system. Together, in addition to the Microsoft Windows system, there are few systems support COM / DCOM, so the Microsoft Windows system is based on the introduction of the following concepts. The COM / DCOM model mainly includes three aspects: (a) the mode written by the program. (B) the binary specification that follows when the program interacts.
(C) an auxiliary environment running. The COM / DCOM basic mechanism is described first by Figure 1. As can be seen from the figure, COM / DCOM is based on client and server models, client programs, and component programs are relative, and function request call is a component program. The component program can also be used as a client to call other component programs, which is the conversion and mutual call relationships of this role make the component program to eventually constitute a software system. The interaction of customer programs and component programs in COM / DCOM can divide components into two types of components and process external components in progress. The so-called internal components refer to the client program and component program in the same process address space; process external components refer to customer programs and component programs in different process space addresses. The internal component is implemented by using the component as a dynamic connection library (DLL), the client is loaded to the component program to call the function of the component program after the component program is loaded. The inner way of these two different components, the client and component program interaction is completely different. However, for the functionality of the functionality and processes, from the perspective of programming, the client program is used by the same method, and the client does not need to make any modifications. Therefore, the programming mode of COM / DCOM is understood by the implementation of the components within the process.
· Internal component: Example: The following is the main content of the COM program instance written in C language: header file: component.h interface decspec_uuid ("100000000000-0000-0000000-000000000") ISUM: Public IUnknown {public : Virtual HRESULT stdmethodCallType SUM (int X, int y, int __rpc_far * retval) = 0;}; client: #include "component.h" const clsid clsid_insidecom = {0x10000002, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x01}}; void main () {IUnknown * pUnknown; ISum * pSum; HRESULT hr = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED); hr = CoCreateInstance (CLSID_InsideCOM, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void * *) & punknown); hr = punkn-> queryinterface (IID_ISUM, (void **) & psum); if (Failed (HR)) cout << "IID_ISUM NOT Supported." << Endl; punknown-> release (); intl; intl; Sum; hr = psum-> sum (2, 3, & sum); if (succeededed (hr)) cout << "Client: Calling Sum (2, 3) =" << Sum << Endl; psum-> release ( Couninitialize ();} component program: #include "component.h" const clsid clsid_insidecom = {0x1000000 2,0x0000,0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}; class cinsidecom: public isum {public: // iUnknown ulong __stdcall addref (); ulong __stdcall release (); hResult __stdcall QueryInterface (Refiid Riid, Void ** PPV); // isum hResult __stdcall sum (int X, int y, int * retval); cinsidecom (): m_cref (1) {} private: ulong m_cref;}; ulong cinsidecom :: AddRef () {RETURN m_cref;}
Ulong cinsidecom :: release () {if (- m_cref! = 0) return m_cref; delete this; return 0;
HRESULT CINSITECOM :: queryinterface (refiid riid, void ** ppv) {if (riid == iid_iunknown) {* ppv = (iUnknown *) THIS;} else if (riid == iid_isum) {* ppv = (isum *) this } Else {* ppv = null; returnif (); returnif (); return s_ok;} HRESULT CINSIDECOM :: SUM (INT X, INT Y, INT * RETVAL) {* RETVAL = x y; returnif;}
class CFactory: public IClassFactory {public: // IUnknown ULONG __stdcall AddRef (); ULONG __stdcall Release (); HRESULT __stdcall QueryInterface (REFIID riid, void ** ppv); // IClassFactory HRESULT __stdcall CreateInstance (IUnknown * pUnknownOuter, REFIID riid, Void ** ppv); cfactory (): m_cref (1) {} private: ulong m_cref;}; ulong cFactory :: addRef () {Return m_cref;} ulong cfactory :: release () {IF (- m_cref ! = 0) return m_cref; delete this; return 0;} HRESULT CFACTORY :: queryinterface (refiid riid, void ** ppv) {if (riid == iid_iunknown) {* ppv = (iUnknown *) THIS;} else f riid == IID_IClassFactory) {* ppv = (IClassFactory *) this;} else {* ppv = NULL; return E_NOINTERFACE;} AddRef (); return S_OK;} HRESULT CFactory :: CreateInstance (IUnknown * pUnknownOuter, REFIID riid, void * * PPV) {cinsidecom * PinsideCom = new cinsidecom; hResult hr = pinsidecom-> queryinterface (RII d, ppv); return hr;!} HRESULT __stdcall DllGetClassObject (REFCLSID clsid, REFIID riid, void ** ppv) {if (clsid = CLSID_InsideCOM) return CLASS_E_CLASSNOTAVAILABLE; CFactory * pFactory = new CFactory; if (pFactory == NULL) return E_OUTOFMEMORY; HRESULT HR = PFactory-> Queryinterface (riid, ppv); Return HR;} Due to the communication between the COM / DCOM system component, it is not necessary to consider the component when writing between the communication between the COM / DCOM system components. The location, the positioning and communication of the components are completed by the system. Therefore, you may wish to analyze the client and component programs. Client program: (1) calls CoinitializeEx initialization. Because many of the program is automatically completed by various services in the library function and the operating system, such as component positioning and loading, and these work is complicated, the program needs to be initialized first. (2) Call COCREATEINSTANCE Create an object.
The first parameter CLSID_INSIDECOM is a 128-bit identifier-class identifier (CLSID), defined in the program to {0x10000002, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, In the future, the 128-bit identification will omit 0x and "-" instead ",", the fourth parameter IID_IUNKNOWN is also a 128-bit ID-Interface Identifier (IID); the 5th parameter (void **) & punknown It is a pointer that it points to the pointer to an interface instance when it returns. CocreateInstance () is a library function that is semantically said to create a COM / DCOM object instance of the corresponding class identifier (CLSID), and obtain an interface instance pointer for the object. For a COM / DCOM object in the process, a COM / DCOM object is implemented in a DLL, and the corresponding relationship of the CLSID and DLL file path is maintained in the Windows system registry. COCREATEINSTANCE first looks for the registry, then load the corresponding DLL program, call the DLL. DllgetClaseObject extraction function (any of the DLLs of the component must provide this function) and some other operations create an object instance. A COM / DCOM object is the only set of interfaces that it contains, each interface is identified by 128-bit IID, and is unique in the entire COM / DCOM system (including distributed on different machines). COM / DCOM system). Any type of COM / DCOM object must support IID_IUKNOWN (identified from 00000000-00000046) interface. There are basically a mechanism in a client program written in different languages to identify interface pointers, COM / DCOM's IIUNKNOWN interface pointer's value to distinguish object without independent object reference, and any object returns to the client during life. The IID_IUNKNOWN interface pointer value must be the same. Note that COM / DCOM does not have the above requirements. COM / DCOM specifies that the IID_IUNKNOWN interface consists of three functions: QueryInterface (const Iid iid, void ** ppv); addref (); release (); and any other interface must also contain these three functions. The addRef and Release are used to control object survival cycles. QueryInter- Face reaches the interface identifies the interface identifies the query object, and the COM / DCOM specifies the QueryInterface function of any interface of the object to obtain the remaining interface pointers of the same object. (3) PunkNown-> QueryInterface (IID_ISUM, (VOID **) & PSUM; obtain another interface instance pointer Psum for the interface identifier for IID_ISUM. (4) HR = PSum-> Sum (2, 3, & sum); Call the member function SUM of the interface via the interface instance pointer PSum. From the perspective of programming mode, the customer program sends a function request to the component program to eventually refer to a member function that is called the interface in the source program, and actually, regardless of the components within the process or the processes of the process. This call to the component component is implemented by calling the function in the same process, but must emphasize that even if the call within the process is still a binary specification, that is, the memory format pointed to by the PSUM in the client program must meet COM / DCOM specification, what is that this specification will be described later.
For a determined interface (IID of the values), its process within the process is not intended for what programming language is implemented, and the generated target DLL returns the memory format pointed to the client's interface pointer. (5) Couninitialize (); call cleaning function. Through the analysis of the customer program, the programming mode of the client can be seen is (a) to create an object instance corresponding to the CLSID; (b) obtain the initial interface pointer of the object; (c) Query other interface pointers by the QueryInterfase function of the interface pointer; d) Call the function of the interface through the interface pointer. (E) Control the life of the object through the interface of addRef () and Release (). The binary norms followed by the client and the process within the process reflect the clause CLSID and interface identity IID; (b) component program must be a legitimate DLL, and leading several standard functions such as DellgetClassObject . (C) Component Program Returns the memory pointed to the client program to meet the COM / DCOM specification. Components: Now analyze the writing of component programs, understand how objects are implemented. First check out the DllgetClassObject function, which will first call the lead function when the client loads the DLL. This function is the most basic entry for the internal components that provide its services, as well as part of the binary specification followed by components within the process. The function of the DllgetClassObject is to determine whether the component supports the type of object according to the CLSID, and one component can support multiple types of objects. DllgetClassObject The corresponding class object is generated according to the CLSID and returns the corresponding interface pointer of the class factory to the client via PPV according to the input parameter const sameid id. Here is the introduction of this new concept that the class is not mentioned in the customer program. According to COM / DCOM specification, component programs must provide a class object for each CLSID that you support, and the class is responsible for creating an instance of the corresponding type of COM / DCOM object. The type of factory object provides an interface commonly referred to as IID_ICLASSFACTory (its value is omitted ") Virtually create an object instance and get the first interface pointer for an object. This shows that the customer program call CocreateInstance library function actually completed the work of two steps, which first requested component to create class factory objects, and then create object instances corresponding to CLSID through class factory objects. In the instance of the above component program, the class is created in the DllgetClassObject function, and the class object is created with New CFactory in CFactory :: CreateInstance. Create a class object via New CinsideCom. The COM / DCOM object is implemented in the form of a C object, and the interface pointer is returned in the form of the object pointer in C . For the internal components, components, and clients are written in writing, while interacting in the same address space in the same address space, the interaction binary compatibility is naturally based on memory format. After understanding the components within the process, the reader is inevitably how to ensure that the client program and component program are written in each other (even using different languages) how to ensure binary compatibility.
As mentioned previously, the component binary compatibility contains three aspects, the identification of the 128-bit identifier, and how to ensure that the legality of the component DLL program is easy, and how to ensure that the interface pointer is in the memory-based interaction The memory format points to match the specification is a bit complex. The next section will introduce the IDL language, which is an important means to solve the above problems.
3. The IDL language is in the example program, whether it is a client or component program that does not use any auxiliary means to meet the binary specification required for COM / DCOM. It is not difficult to imagine: the general C procedure that meets a certain structure has been compiled. The binary code produced is to meet the COM / DCOM binary specification. It is also difficult to imagine: In order to meet the COM / DCOM binary norm, a simple method is to limit the format of the source program for generating the target code, and the C program in the example clearly needs to define the C class definition of the object. It is possible to make a restriction. At the same time, it is obvious that the COM / DCOM is independent of the programming language. The header of the C must be clearly can't do, so a separate language must be used to describe the interface. The language selected by Microsoft is IDL. The IDL language is an Open Software Foundation (OSF) is developed for distributed computing environment RPC software packages. The IDL helps RPC programmers guarantee the project client and server to comply with the same interface. In order to apply the IDL language to the COM / DCOM system, Microsoft has expanded the syntax of the IDL language. The IDL itself is not a programming language, which is a tool for defining the interface, as for the interpretation of the IDL language is determined by using its system. COM / DCOM is closely related to the interpretation of the IDL language and COM / DCOM's binary norms, and such interpretation and other systems that utilize IDL have no relationships. COM / DCOM usually does not directly translate the interface defined by the IDL language into binary code. C language users use Microsoft's MIDL.exe programs to translate the IDL language into a corresponding C header file. The header file in the above example is generated by the following IDL file, and interface ISUM inherits the interface IUNKNOWN. The interface definition file accurately describes the functions, functions of the interface, and the type of parameters. Import "unknwn.idl"; [Object, UUID (100000000000001)] Interface isum: iunknown {hResult SUM ([in] int x, [in] int y, [out, return] INT * RetVal);}; where unknwn.idl is system predefined, the content is as follows: [Local, Object, UUID (00000000-0000-0000-C000-000000000046),] Interface iunknown {HRESULT QueryInterface ([in] refiid riid, [OUT, IID_IS (RIID)] void ** ppvobject); ulong address (); ulong release ();} The C header generated by the IDL is included in the client program and component programs, respectively, by #include. Using the C header file translated by MIDL.exe ensures that the memory structure refers to the memory structure referred to in the client program and the component program, solves the interoperability between the components implemented by the same programming language; on the other hand, it is ensured The memory structure referred to in the interface pointer complies with COM / DCOM's binary specification, solving interoperability between components implemented in different programming languages. However, because Microsoft's MIDL.EXE does not directly generate other languages (such as VB, Java) corresponding header files through the IDL file, users need other tools to utilize IDLs, which are not described here. 4. The inheritance of the component object has the basic characteristics of the component object model, where the object is encapsulated, and it has been discussed before the polymorphism. But another important feature of the object model - inheritance --- has not been involved. COM / DCOM provides similar features through inclusion and aggregation.
A common feature of inclusive and aggregation is that object inclusive and aggregate must make customers believe that it is an object. As mentioned earlier, the unique logo of the client's different object is the value of the object's IID_IUNKNOWN interface pointer, and the QueryInterface function of the interface through the same object must be able to query other interfaces of this object. Figure 2 shows an implementation of inclusive and polymerization, object B implement interface IID_IB and IID_ID_ID_ID_ISUM, where IID_ISUM's function is done by creating another CLSID_INSIDECOM type. As shown in the figure, when using an inclusive mode, the object B simply creates a CLSID_INSIDECOM object, and the customer program all the call to the object B interface IID_ISUM can be done with the IID_ISUM interface of the CLSID_INSIDECOM object. When using the aggregation mode, the object B still creates a CLSID_INSIDECOM object, but the object B does not implement the IID_ISUM interface but to return the interface pointer of the CLSID_INSIDECOM object to the client, in the usual implementation, object B and CLSID_INSIDECOM objects Save each other's IIT_IUNKNOWN interface pointer, when the customer requests the QueryInterface function of the interface pointer of the object B, the object B will pass the request to the QueryInterface function of the IID_IUNKNOWN interface pointer of the saved CLSID_INSIDECOM object and vice versa. Most importantly: Whether it is in the object B or in a CLSID_InSideCom object, the IID_IUNKNOWN interface pointer must be returned when the client requests the IID_IUNKNOWN interface pointer. 5. Process Outgoing Components • Overview Process Extractions Usually an independent executable, that is, an .exe file. Process external components can be run independently, and it communicates with the client program via LPC (local process call) or RPC (remote procedure call). The client and component program use RPC to communicate when running on different machines, which will be introduced in this case to write mode and interaction between the client and component programs. The client program uses the programming mode when using the process outsourcing and the programming mode when using the components in the process. The customer only needs to create a CLSID object, and the location of the program entity that creates this object is transparent to the customer. The system is determined. The COCREATEINSTANCE function is determined by the Query System Registry to load an internal component DLL or notify the system service on another machine to start a process external component executable program. The client also has the ability to limit the components used by COCREATEINSTANCE. The programming mode of the component program is slightly different. The component programs need to create all kinds of factory objects that are supported, then through the library function CoregisterClassObject Registration Class, and start listening to the client's RPC request, the instance code is as follows: IclassFactory * PclassFactory = New Cfactory (); DWORD DWREGISTER; COREGISTERCLASSOBJECT (CLSID_INSIDECOM, PCLASSFAACTORY, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, & DWREGISTER); The above code is located in the main function of the program. The binary compatibility of the analysis client and component program interacts will be examined after investigation. When in the address space of the same process, binary compatibility of the client and component is based on memory. When both are in different machines, binary compatibility is naturally based on RPC communication.
The above description is not difficult to understand, and it is difficult to understand how the client is operated in another process address space through the interface pointer, which involves proxy / stub (proxy / stub), column / scattered Marshaling / Unmarshaling and other concepts, the following will be an introduction to this. • Process Transparency Customer After Creating a component object, it calls the member function of the component object by the interface pointer, but in fact, the interface pointer refers to the proxy object (Proxy) in this process, and the customer call is a proxy object. The member function, by the proxy object passing through the calling method of the process (LPC / RPC) to the settlement code (STUB) communication in the component process, the setup of the objects in the component, and the order of the function returned is just the opposite. The proxy object is responsible for the process of calling the call, the parameter called column set, the resulting result is a data packet conforming to the COM / DCOM binary specification. After the data packet is passed to the stub code by the proxy object, the packet is first has been has been handled by the stub code, and the stub code calls the corresponding function of the object in the component obtained after processing. The above process can be represented by Figure 3. There are a variety of methods for the realization of proxy objects and stub codes, one of which is called standard column (STANDARD MARSHALING). When using a standard column set, the agent object and the stub code itself are composed of the COM / DCOM object. These objects are implemented by the components within the process. The corresponding DLL is loaded in the user's invisible method, so the customer program can use the process in the same way. Internal assemblies and processes. Next, a proxy object is further explained. When using a standard column set, the agent object is actually not a single object, but is polymerized by a number of COM / DCOM objects in different DLLs, which can easily give customers several objects as the same object by aggregation. One of the objects is called a proxy manager, which is implemented by Microsoft's DLL, which is responsible for providing public services such as communications. For each interface (identified by the IID), there is a corresponding DLL, the implementation of the interface proxy object in the DLL is mainly responsible for the column / hash processing of each function in the interface, while the column / hash interface pointer Responsible for dynamically create a proxy object of other interfaces. The C source program of the interface DLL can automatically generate by MIDL.EXE according to the IDL file of the defined interface. After the connection can generate the target code, the system registry manages the correspondence between the interface ID (IID) and the interface DLL path name. Summary COM / DCOM is a simple distributed component object model, which is very simple and clear, which can be easily combined with the functionality in different components using this model. This model is Microsoft's development of its operating system and application, in order to solve specific problems, it is not as comprehensive as Corba, and there is not much consideration and facility guarantee for the distribution of components. It can be said that COM / DCOM specifies the interaction between components in the easiest way, but even in this way, the Microsoft operating system based on COM / DCOM and applications such as Office, Internet Explore are still useful.