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 will
Some functions that must be used are statically connected 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 have ATL. dll
File support. 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 may be reported during compilation.
Lnk2001: unresolved external symbol
_ Main ". 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
The minimum CRT used 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? Use
. H file description? ------ It's really convenient for C programmers to laugh! Basic programmers 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. Specific IDL
For more information about the file, see the next "COM Component Design and Application (8) Add a new interface". After the IDL is compiled, the binary equivalent library file TLB is generated.
It 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"); // get the registration function pointer
// If it is not registered, 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 this component needs to load some required DLL at the same time during loading,
It is possible that it cannot be correctly located due to its own program bug. Well, let's make up for the program we have written. Who makes us good?
Who makes our level higher 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 ":
For original operations
Port pointers are troublesome. We need to control reference records, API calls, and exception handling by ourselves. So ATL
Provides two smart pointer template packaging classes, ccomptr <> and ccomqiptr <>.
<Atlbase. h>. Ccomqiptr <> contains
Ccomptr <> all functions, so we can use ccomqiptr completely <>
To use smart interface pointers, the only thing to note is: ccomqiptr <>
Because the overload function of the operator is used, it will automatically call the QueryInterface () function for us. Therefore, ccomqiptr <>
The only drawback is that the iunknown * pointer cannot be defined.
// Smart pointer, which indicates the variable type starting with SP according to the Hungarian naming method
Ccomptr <iunknown> spunk; // correct
// Assume that ifun is an interface type
Ccomptr <ifun> spfun; // correct
Ccomqiptr <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 obtained by calling QueryInterface () through the common interface pointer potherinterface
Ccomqiptr <ifun> spfun (spotherinterface); // call the constructor. The internal interface pointer value is
// The ifun interface pointer obtained by calling QueryInterface () through spotherinterface.
Ccomqiptr <ifun> spfun (punknown); // call the constructor. The ifun interface pointer is obtained by QueryInterface () of iunknown.
Ccomqiptr <ifun> spfun = potherinterface; // = Operator overload, meaning the same as above
Spfun = spotherinterface; // same as above
Spfun = punknown; // same as above
Punknown-> QueryInterface (iid_ifun, & SP); // you can assign a value through QueryInterface.
// After assigning values to smart pointers, you can use conditional statements to determine whether the values are valid or not.
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 function: 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 is the same as that of spfun. QueryInterface (...).
Spfun-> QueryInterface (...);
Spfun. Release (); // release the internal interface pointer, and the internal pointer value is 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.