COM Component Design and Application (7) Compile, register, and call
Author: Instructor Yang I. Preface In the last two times, we used ATL to write the first COM component program. This time, we mainly introduce compilation, registration, and calling methods. Have you downloaded the sample program? If you have not downloaded the file, click here for the vc6.0 user and click here for the vc.net user.
Ii. Compilation
2-1 minimum dependency "Minimum dependency" indicates that the compiler statically connects some functions that must be used in ATL to the target program. In this way, the size of the target file will be slightly larger, but it is more independent and easy to install. On the contrary, the system needs to support the ATL. dll file during execution. How do I select "minimum dependency? The answer is: Delete the predefined macro "_ atl_dll". For the operation method, see Figure 1 and figure 2. Figure 1. Setting Method in vc6.0
Figure 2. Setting Method in vc.net 2003
2-2 CRT Library If the library function of the CRT Runtime is called in the ATL component program, such as square SQRT (), an error "error lnk2001: unresolved external symbol _ main" may be reported during compilation ". What should I do? Delete the predefined macro "_ atl_min_crt "! For the operation method, see Figure 1 and figure 2. (This project attribute in vc.net 2003 is called "minimum use of CRT in ATL ") 2-3 MBCS/Unicode This is not much to mention. In the predefined macros, _ MBCS or _ Unicode are used respectively. 2-4 IDL Compilation At the early stage of the design, COM set a goal to achieve cross-language calls. Since it is cross-language, the component interface description must be known in any language environment. What should I do? Description in the. h file? ------ It's really convenient for C programmers to laugh! The Basic programmer cried:-(therefore, Microsoft uses a new file format-IDL file (interface definition Description Language ). IDL is a text file, and its syntax is relatively simple, like C. For details about the IDL file, see the next "COM Component Design and Application (8) Add new interface". After IDL compilation, the equivalent Type Library File TLB that generates binary data is provided to other languages for use. Figure 3 illustrates the compilation process of the atl com program: Figure 3. ATL component program compilation process
Note 1: After compilation, the Type Library exists separately in the form of a TLB file and is also stored in the resource of the target file. Therefore, we can specify both the TLB file and the target file when # import introduces the Type Library in the future; NOTE 2: As C/C ++ programmers, we are quite happy. This is because after the IDL compilation, We are specially provided with an interface file in the C language format. NOTE 3: After IDL is compiled, a proxy/stub source code is generated, including dlldata. c, xxx_p.c, xxxps. def, xxxps. mak, we can use nmake. EXE re-compilation to generate the real proxy/stub DLL target file (note 1 ). Iii. Registration Case 1:When we use ATL to write component programs, we are not responsible for registration. After the compilation is successful, IDE will automatically register for us; Case 2:When we use MFC to write component programs, since the compiler does not know whether you are writing a COM component, it will not help us automatically register. At this time, we can execute the menu "tools \ register control" to register. Case 3:When we write an EXE program with the com function, the registration method is to run this program once; Case 4:When you want to use the third-party component program, you can run the *** regsvr32.exe filename *** to register the program. In other words, the reverse registration is based on the regsvr32.exe/u file name "; Case 5:When we need to execute registration in the program (such as the installation program), then: Typedef hresult (winapi * freg) (); tchar szworkpath [max_path];: getcurrentdirectory (sizeof (szworkpath), szworkpath); // Save the working directory of the current process :: setcurrentdirectory (component directory); // switch to the component directory hmodule hdll =: loadlibrary (component File Name); // dynamically load the component if (hdll) {freg lpfunc = (freg ):: getprocaddress (hdll, _ T ("dllregisterserver"); // obtain the registration function pointer. // if it is a reverse registration, you can obtain the "dllunregisterserver" function pointer if (lpfunc) lpfunc (); // execute registration. For simplicity, the return value is not determined: freelibrary (hdll) ;}:: setcurrentdirectory (szworkpath); // switch back to the original process working directory In the preceding example, the code part for switching the working directory can be simplified in most cases. However, if the component needs to load some required DLL at the same time during loading, it may fail to be located due to its own program bug. Cough ...... let us write our own program to make up for its errors ...... who makes us good people, who makes us better than him? Who makes us a "eye-catching" on vckbase ...... IV,About component calls In general, calling a component program involves the following methods:
# Include Method |
After IDL compilation, XXX. h and xxx_ I .c files will be generated to facilitate the use of C/C ++ programmers. We are so happy that we can use it directly after # include. |
# Import Method |
More common methods, VC will help us produce packaging classes, making our calls more convenient |
Method for loading Type Library packages |
If the component provides the idispatch interface, using this method to call the component is the easiest. I haven't talked about idispatch yet. I can only read later articles. |
Method for loading ActiveX packages |
ActiveX hasn't been introduced yet. Let's talk about it later. |
After downloading the sample program, browse the usage items one by one:
Example |
Method |
Brief Description |
1 |
# Include |
Completely call components using the most basic API methods, so that you are familiar with the call Principle |
2 |
# Include |
Most of the APIs use ccombstr to simplify the use of strings. |
3 |
# Include |
Demonstrate how to use smart pointer ccomptr <> |
4 |
# Include |
Demonstrate how to use a combination of smart pointer ccomptr and ccomqiptr |
5 |
# Include |
Demonstrate how to use smart pointer ccomqiptr <> |
6 |
# Include |
Demonstrate how to release smart pointers |
7 |
# Import |
How to Use and handle smart pointers ixxxptr, _ bstr_t, and _ variant_t packaged by VC |
8 |
# Import |
How to Use the imported namespace |
Annotations are written in the sample program. Please read carefully and refer to the Function Description of msdn. Here, I will introduce you to "smart Pointers ": It is troublesome to operate the original interface pointer. We need to control the reference records, API calls, and exception handling by ourselves. Therefore, ATL provides two smart pointer template packaging classes, ccomptr <> and ccomqiptr <>, both of which are declared in <atlbase. h>. Ccomqiptr <> includes all the functions of ccomptr <>. Therefore, we can use ccomqiptr <> to use smart interface pointers. The only thing to note is: ccomqiptr <> because the operator overload function is used, it automatically calls the QueryInterface () function. Therefore, the only drawback of ccomqiptr <> is that the iunknown * pointer cannot be defined. // Smart pointer. According to the Hungarian naming method, it generally starts with SP to indicate the variable type ccomptr <iunknown> spunk; // correct // assume that ifun is an API type ccomptr <ifun> spfun; // correct ccomqiptr <ifun, & iid_ifun> spfun; // correct ccomqiptr <iunknown> spunk; // error! Ccomqiptr cannot define the iunknown pointer Assign values to smart pointers: Ccomqiptr <ifun> spfun; // call the constructor without assigning a value. The encapsulated Internal interface pointer is null ccomqiptr <ifun> spfun (potherinterface); // call the constructor, the internal interface pointer value is // The ifun interface pointer ccomqiptr <ifun> spfun (spotherinterface) obtained by calling QueryInterface () through the common interface pointer potherinterface. // call the constructor, the internal interface pointer value is // The ifun interface pointer ccomqiptr <ifun> spfun (punknown) obtained by calling QueryInterface () through spotherinterface. // call the constructor, obtain the ifun interface pointer ccomqip from QueryInterface () of iunknown. Tr <ifun> spfun = potherinterface; // = Operator overload, meaning the same as above spfun = spotherinterface; // same as spfun = punknown; // same as punknown-> QueryInterface (iid_ifun, & SP); // You can also assign a value through QueryInterface // After assigning a value to a smart pointer, you can use a Condition Statement to determine whether the value is valid. If (spfun) {} // if the pointer is valid if (null! = Spfun) {}// if the pointer is valid if (! Spfun) {}// if the pointer is invalid if (null = spfun) {}// if the pointer is invalid How to call a function using a smart pointer: Spfun. cocreateinstance (...); // equivalent to the API function: cocreateinstance (...) spfun. queryInterface (...); // equivalent to API functions: QueryInterface () spfun-> Add (...); // call the interface function of the Internal interface pointer // call the QueryInterface () function of the Internal interface pointer, in fact, the effect and spfun. queryInterface (...) same as spfun-> QueryInterface (...); spfun. release (); // release the internal interface pointer, and assign the internal pointer to null spfun-> release (); // Error !!! Do not use this method. // Because this call does not clear the internal pointer, The Destructor will be released again (released twice) Cough... don't talk about it, don't talk about it. Read more books, read more msnd, and read more sample programs. Tired of writing :-( V. Summary Stay tuned to COM Component Design and Application (8) ------ how to add the second interface in the ATL component Note 1: it is a little troublesome to compile the proxy/stub. We will introduce the "out-of-process components" and "Remote components" later. In vc.net 2003, it is relatively simple because the proxy/stub is automatically added to our solution as a separate project. |