COM component model basic one, dynamic link library: Dynamic link library is the load object of most COM components (don't care about OCX, which is also a DLL, but it has changed a suffix). Of course, EXE is also possible (TEXTOSPEECH object in TTS is an example), but it is much less in fact. In the early days of Windows, the appearance of dynamic link libraries was a revolution. It changed the life of Windows, and also lay a solid cornerstone for the dominant position of today's Windows operating system. (About Windows's historical problem, I have never been clear. Please write the historians of vckbase to write an article as soon as possible ^ _ ^). Microsoft's dynamic link library is this explanation: Dynamic Link Library (DLL) is an executable file as a shared function library. Dynamic links provide a method that allows the process to call a function that does not belong to its executable code. The executable code of the function is located in one DLL, which contains one or more functions that have been compiled, link and separately stored with their processes. The DLL also helps share data and resources. Multiple applications can access the contents of a single DLL copy in the memory. Well, it's very clear. The dynamic link library is first a executable file (Microsoft explained that EXE is called a direct executable file), which contains a set of functions that need to be shared. When used, a dynamic link library (and Windows system) provides a method to make our application to call the functions. In addition, the dynamic link library also contains some resources (such as icons, dialog templates, etc.). In MFC, Microsoft applies some techniques to provide some additional functions on the basis of existing dynamic link libraries, such as the export of the MFC class. Dynamic link links are roughly divided into two categories: static links and dynamic links. Static links are also implicit links, this link mode makes us no statement in the code to indicate which dynamics do our applications Link library. Its static link declares is placed in the engineering attribute (or uses #pragma comment (lib, "xxx.lib"), which can be placed with #include). At designation, you only need to enter the corresponding import library file (.lib) of its dynamic link library. You can then call the function in the dynamic link library anywhere in the program (of course, you need to include its corresponding header file. In general, the header file will give a piece of the lib file. ). The program generated by this method is initialized (when the specifically is not very clear. But I can definitely be before the Winmain function is ^ _ ^), will automatically load the dynamic link library in the system environment and will It is mapped to our application process. When we call a function that is not defined by our process, the VC runtime will find the function of the corresponding dynamic link library by finding the relevant information of the lib file and calls it. At the end of the process, the system will load the dynamic link library. Dynamic links are also explicit links, as the name referway, we must explicitly load the dynamic link library by calling the API by calling the API. All COM component models all use this way to load the component module (already DLL). (I think Microsoft's professional term is a chaos.). This approach has many benefits, it can decide which link library to load at runtime, which function is to call ... This is called dynamic link. It is not difficult to use the dynamic link library, first to call LoadLibrary, whose prototype is as follows: HModule LoadLibrary (LPCTSTR LPFILENAME / / File Name of Module); Parameter LPFileName is the file name of the dynamic link library to load. If the load is successful, it returns its handle. Otherwise, return NULL. The prototype is as follows: Bool Free HModule (HModule HModule); Bool Free HModule (HModule HModule); I don't have to say more. When the dynamic link library is loaded by LoadLibrary, the C run library completes the initialization of the dynamic link library through _dllmainCrtStartup, such as the global object (variable), the generation of static member variables, and the initial value.
The most important thing is that it also calls the DLLMAIN function. Each dynamic link library must have this function, just like the application must have Main or WinMain. Its prototype is: BOOL WINAPI DLLMAIN (Hinstance Hinstdll, // Hinstance Hinstdll, // Handle To The DLL Module Dword Fdwreason, // Reason for Calling Function LPVOID LPVRESERVED ////r "; you can complete your dynamic link library through the dllmain function Initialization and destructive operation. Ah, things are like this: Dllmain has four situations, these four situations can come from the fdwreason parameters: They are 1. DLL_Process_attach, call DLLMAIN when the dynamic link library is loaded. 2. DLL_THREAD_ATTACH, when the process creates a new thread, the process will call the DLLMAIN that has been loaded with the dynamic link library. 3. DLL_THREAD_DETACH, when a thread ends, the process will call the DLLMAIN that has been loaded with the dynamic link library. 4. DLL_THREAD_DETACH, when the dynamic link library is loaded or the process is completed, call DLLMAIN. In this way, the life cycle of a dynamic link library can be reacted by the DLLMAIN function. When we succeed, we will get an HMODULE handle. The use of this handle is very similar to the handle of the Hinstance application instance (Tracing definition, HModule is hinstance). We can use some of the following API functions: loadbitmap, loading, loading, ..., getprocaddress, etc., the most important thing is GetProcAddress. It is a function pointer for returning a function in the link library, and then we can call this link library function through this function pointer. (If you are not familiar with the function, it is best to look at the C / C grammar book. I think the declaration of the function pointer is very weird) The prototype is as follows: FarProc getProcaddress (HModule HModule, // Handle to DLL Module LPCSTR LPPROCNAME // function name);, hmodule, I don't say it. The LPPROCNAME parameter is a string that writes the function name of the function we have to find. If you find it, return the pointer to this function, otherwise returns NULL. For example: For example, there is a link library function is "int Plus (int Naugend, Int Nadde", I want to call it. HModule hmathlib = loadLibrary ("math.dll"); int (* myproc) (int, int) = null; int x = 1, y = 1; myproc = (int (int, int)) getProcAddress (HMATHLIB , "Plus"); if (myProc! = Null) {Printf ("% D", (* myproc) (x, y));} freeelibrary (hmathlib); if I have no problem, I want to The output result should be 2. I still think that the declaration of the function pointer is very weird, readability is not high, so I usually change a way of writing.
#define DefMathProc (name) int (* name) (int, int) #define FUNCTION (name) (* name) DefMathProc (MyProc) = NULL; MyProc = (DefMathProc ()) GetProcAddress (hMathLib, "Plus"); nResult = Function (MyProc) (x, y); Although I will have a warning, I think this will feel comfortable. Well, the situation of dynamic links is basically so. The specific dynamic link library is written and a copy of the COM component is talking in subsequent chapters. Second, the object-oriented component model -comwindows system dominant status is not shaken in three or four years. Therefore, there is a multi-multi-Windows development platform appeared in front of us. n A variety of development languages are all flowers. So, in the Bible, we have a different language and cannot communicate with each other. In order to change this reality, cute Bill stands out, "I have to change the world!" Microsoft has developed a binary universal interface specification -Component Object Model (Component Object Model). However, the solution to the COM is not intended for a general interface, but is applied to the implementation of the composite document (OLE). And now due to language irrelevant, process transparency, reusability, confidentiality (unless the master master is high, anyone can see the technology from the assembly code), and write is not difficult, so development has become an application A wide range of technologies. 1) Component objects and interface components objects, the interface is the foundation of COM. Below, please allow me to make a class ratio with the C object. The meaning of the component object and the C object is basically the same. It is a function, attribute and logic. It is an entity object that can be used with the features it provides by operating it. The interface is equivalent to the public member in the C object. It is exposed to the external user, and the user is only allowed to call these features that are exposed outside to use objects. Unlike public members, the interface is not a variable is not a function, but it should be a set of functions. Logically, this group function should be functional. A component object can have many interfaces. I only know the COM implementation method of C , as for dephi, I don't know anything. The C implementation method is to complete the implementation of the component object by the C class object, which is represented by the C pure virtual class. C class objects have multiple interfaces by multiplex multiple interfaces. Below, I will give an example to explain the relationship between the component objects and the interface in C (the example below is not a COM implementation, just to indicate the relationship between the component object and the interface) I want to do a person's component object, I must first define some interfaces to represent people's external performance behavior. class physiology {public: virtual void eat (Food in) = 0; virtual void drink (Liquid in) = 0; virtual Somethings toilet () = 0;}; class psychics {public: virtual Sound laugh () = 0; virtual Sound CRY () = 0; Virtual Sound Angry () = 0;}; Class Dynamics {public: Virtual Speed Run () = 0; Virtual Speed Walk () = 0; Virtual Interval Jump () = 0;}; I will The behavior is divided into three types of physiology, psychology and dynamics, allowing them to express different behaviors. So, such a related function is three interfaces.
The implementation of the C component object is to derive more from these interfaces and achieve them. In this way, we get a component object (declaration, this example is just a concept, the real COM component object also needs to add some Dongdong). Class Human: Public PHYSIOLOGY, PUBLIC PSYCHICS, PUBLIC DYNAMICS {public: Void Eat (Food In) {cout << "Good! Very Delicious!";} Void Drink (Liquid IN) {cout << "NO! I am NOT DRUNK ! ";} Something toilet () {cout <<" hum ... "; return devt ();} Sound laugh () {Return Sound (" ha ... ha ... ha ");} Sound Cry () {Return Sound ("DAD! DON't Beat My BUNS.");} Sound angry () {RETURN SOUND ("Where Did You Go Last Night? Darling.");} Speed Run () {COUT << "Run, Police Come ! "; Return 20km / h;} speed walk () {cout <<" OUT. YEGG, I am No ... not Afraid o ... .of y ... you. "; Return 1M / S;} Interval jump () {cout << "" Yeah .... "; Return 4M;}}; this, one component object is defined. When using component objects, a pointer gives you. It is a virtual class pointer implemented by a component object. We can use it to call the functionality implemented by the component object (of course, we have the right to choose any virtual category; as long as the component object supports) . In summary, an external feature of a component object is composed of different interfaces, which is the function provided by the user to display the components. Note: If your C virtual function is not very good, please find a C grammar to see it. Or please see the "Analytical Dynamic Connected" of the VCKBase 12th. 2) The identifier (GUID) above, I said the COM component is based on binary. Then we want to use the signature (such as a class name, interface name) to specify a component obviously unmembacted (at least in terms of identification). So, since it is the most convenient to use the binary system, it is of course used to use the number identity. So Microsoft defines such a structural standard: typedef struct _guid {dowrd Data1; Word Data2; Word Data3; Word Data4 [8];} GUID; Structure is used to store some digital information, to meet a COM object, interface, other COM elements. This structure is called the identifier. One identifier in C is said: Extern "C" const guid clisid_myspellchecker = {0x54BF6567, 0x1007, 0x11d1, {0x45, 0xAa, 0x44, 0x45, 0x53, 0x54, 0x45, 0x53, 0x54, 0x00, 0x00}} The same identifier is in other This is said in a non-C environment: {54BF6567-1007-11D1-B0AA-444553540000} This identifier represents a COM object because the identifier of a COM object is prefixed in CLISID_. The name of the interface is prefixed in IID_. Don't ask me, the identifier definition is related to the specific relationship. I do not know. They have nothing to do at all.
When a COM object is written, we use a random way to determine its identifier (this work can be helped by the VC.). Once the COM object gets an identifier and release it, then it cannot be changed. In addition, don't worry that GUID will conflict. If your high school mathematics has already, please count how much the probability of repetition is counted in 128-bit binary. If you really find the guid conflict (you have to ensure that this is not a person), I suggest you come to buy a lottery. You are not far from 5 million. 3) IUNKNOWN Interface COM Mode All Interfaces must comply with certain specifications, which is the source of the IunkNown interface. Each interface must be inherited from this interface. In C , Microsoft has for us the good IUnknown defined: typedef GUID IID; class IUnknown {public: virtual HRESULT _stdcall QueryInterface (const IID & iid, void ** ppv) = 0; virtual ULONG _stdcall AddRef () = 0; virtual Ulong _stdcall release () = 0;}; Note: Void * can point to any object. I didn't understand the void * when I started. The reason here used is uncertain from the passage and incoming pointer type. The QueryInterface function function is to help when we get an interface pointer and we want to get another interface pointer. We will pass the identifier of the interface we want to give to the IID, and will make a pointer to the PPV. If QueryInterface is successful, it will return S_OK. Our pointer will point to the interface we want. AddRef, Release is used to implement reference counting mechanisms. In a binary system, component objects have a clear survival in the C environment. This situation may occur, two (or more) places (possibly between different programs, may also be between the simultaneous use of a component object, if one of the places delete off components Object. It is impossible else to know that when they try to call this image, it will cause serious injuries, and the weight will lead to death. This is not what we want to see. Thus, the COM model sets a reference counting mechanism. When a place starts using an object, it must call addRef () once. When we use QueryInterface, QueryInterface must call us atten (). AddRef () will increase the reference count of the component object. When this place no longer uses an object, it must call Release () once. Release () will reduce the reference number of the component object by 1. When the reference count of the component object becomes 0, it indicates that no one will use the component object again. At this time, the component object should end your life. This ensures that the security of other programs during the survival of the component object is guaranteed. Of course, you can use your own reference mechanism, as long as your behavior supports AddRef and Release. For example, the reference count of the object is not set, but set a reference count for each interface. When all the interface reference counts are 0, the delete object. Ok, in the previous example, I didn't abide by the Iuknown specification. Here I have to obey it. I used the same thing in the same time ... I omitted.
// {6AAF876E-FCED-4ee0-B5D3-63CD6E2242F5} static const GUID IID_IPhysiology = {0x6aaf876e, 0xfced, 0x4ee0, {0xb5, 0xd3, 0x63, 0xcd, 0x6e, 0x22, 0x42, 0xf5}}; class IPhysiology: public IUnknown { public: ......}; // {183FC7A1-4C27-4c38-B72D-D1326E2E8A7C} static const GUID IID_IPsychics = {0x183fc7a1, 0x4c27, 0x4c38, {0xb7, 0x2d, 0xd1, 0x32, 0x6e, 0x2e, 0x8a, 0x7c}}; class IPsychics: public IUnknown {public: ......}; // {5F144D5C-A20C-42e7-8F91-4D5CAE430B29} static const GUID IID_IDynamics = {0x5f144d5c, 0xa20c, 0x42e7, {0x8f, 0x91, 0x4d, 0x5c, 0xae, 0x43, 0xb, 0x29}}; class IDynamics: public IUnknown {public: ......}; // {ABFA7022-7E2F-4d0e-8A4F-F58BBCEBB2DA} static const GUID CLISID_Human = {0xabfa7022, 0x7e2f, 0x4d0e, {0x8a, 0x4f, 0xf5, 0x8b, 0xbc, 0xeb, 0xb2, 0xda}}; class human: public IPhysiology, public IPsychics, public IDynamics {public: ...... human () {m_ulRef = 0;} HRESULT QueryInterface (const IID & iid, void ** ppv) { IF (IID == iid_iunknown || IID == iid_iphysiology) {* ppv = static_cast
The IDL description and graphical description of our component object is given below #include "oLECTL.H" Import "OAIDL.IDL"; Import "OCIDL.IDL"; [Object, UUID (6AAF876E-FCED-4EE0-B5D3-63CD6E2242F5), nonextensible, helpstring ( "IPhysiology Interface"), pointer_default (unique)] interface IPhysiology: IUnknown {void eat (Food in); void drink (Liquid in); Somethings toilet ();}; [object, uuid (5F144D5C-A20C- 42e7-8F91-4D5CAE430B29), nonextensible, helpstring ( "IPsychics Interface"), pointer_default (unique)] interface IPsychics: IUnknown {Sound laugh (); Sound cry (); Sound angry ();}; [object, uuid (5F144D5C -A20C-42e7-8F91-4D5CAE430B29), nonextensible, helpstring ( "IDynamics Interface"), pointer_default (unique)] interface IDynamics: IUnknown {Speed run () = 0; Speed walk () = 0; Interval jump () = 0 [UUID (6CC7B329-B92F-4A8F-9CDD-1AB6D7E4CF4D), Version (1.0), Helpstring ("OleObject 1.0 Type Library")] library oleobjectlib {importlib ("stdole2.tlb"); [UUID (62fd0e39-da84 -4B19-Bab0-960a27ac2b71), Helpstring ("Olepaint Class")] Coclass Olepaint {[Default] Interface iPhysiology, in Terface ipsychics, interface idynamics};}; Please detail, observe the above description IDL code and graphics. Not too hard. 4) Interface principles of COM objects In order to standardize the interface mechanism of COM, Microsoft has released the interface principles of COM objects to COM developers. (1) IUNKNOWN Interface Equity When we have to wait until two interface pointers, how do I determine that they are from one object. The principle of COM interface stipulates that the IUNKNOWN of QueryInterface in the same object should be equal. That is, the iUnknown refer to each object is unique. We can determine whether they point to the same object by judging if the IUNKNOWN pointer is equal.