Original: http://vckbase.com/index.php/wv/1218.html
First, preface
In two, we wrote the first COM component program with ATL, which focuses on compiling, book, and calling methods. Have you downloaded the sample program? If not yet downloaded, vc6.0 's user point, Vc.net's user point here.
Second, about the compilation
2-1 Minimum Dependency
"Minimum dependency" means that the compiler will statically connect some of the functions that must be used in ATL to the target program. This will make the target file size slightly larger, but more independent and easy to install, whereas ATL is required for system execution. DLL files are supported. How do I choose to set to "minimum dependency"? The answer is: Delete the pre-defined macro "_atl_dll", the Operation method is shown in figure I, figure ii.
Figure one, in the vc6.0, the Setup method
Figure II, in Vc.net 2003, the Setup method
2-2 CRT Library
If you call the CRT Runtime library function in an ATL component program, such as Open square sqrt (), you may get an error "error lnk2001:unresolved external symbol _main" when compiling. What to do? Delete pre-defined macro "_ATL_MIN_CRT"! The operation method is also shown in figure I, figure ii. (The Project property in Vc.net 2003 is called "the smallest CRT in ATL")
2-3 Mbcs/unicode
This is not much to say, in the predefined macros, use _MBCS or _unicode respectively.
Compilation of 2-4 IDL
COM in the early stages of design, a goal was set: to be able to implement cross-language calls. Since it is cross-lingual, the interface description of the component must be recognized in any locale. What to do? Describe with the. h file? ------C language Programmer laughed, really convenient! The BASIC programmer cried:-( As a result, Microsoft has used a new file format---IDL file (interface Definition description language). IDL is a text file, its language syntax is relatively simple, very much like C. The specific IDL file, see the next time, "COM Component design and application (eight) add a new interface." IDL is compiled and generated binary equivalent type library file TLB is available for use in other languages. Figure three illustrates the process of compiling an ATL COM program:
Figure III, ATL component program compilation process
Illustration 1: After compilation, the type library exists separately as a TLB file and is also saved in the resources of the destination file. Therefore, we can specify the TLB file or the target file when we introduce the type library in the future #import;
Note 2: We are a C + + programmer, but also more happy. Since IDL compiles, we have specially provided the C language interface file.
Description 3:idl build agent/root source program after compiling, there are: dlldata.c, xxx_p.c, Xxxps.def, Xxxps.mak, we can use NMAKE. EXE is compiled again to produce a real proxy/stub DLL target file (note 1).
Third, about registration
Scenario 1: When we use ATL to write component programs, registration is not our responsibility. After compiling successfully, the IDE will help us to register automatically;
Scenario 2: When we use MFC to write a component program, because the compiler does not know if you are writing a COM component, it does not automatically register for us. At this time, we can execute the menu "Tools\register Control" to register.
Scenario 3: When we write an EXE program with COM functionality, the method of registration is to run the program once;
Scenario 4: When we need to use a third-party-provided component program, you can register it by running "Regsvr32.exe file name" on the command line. By the way, the anti-registration method is "regsvr32.exe/u filename";
Scenario 5: When we need to perform a registration in a program (such as a setup 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's directory hmodule hDLL =:: LoadLibrary (component file name);//dynamic load component if (hdll) {Freg Lpfunc = (freg):: GETPR Ocaddress (hDLL, _t ("DllRegisterServer"));//Get Registered function pointer//If it is anti-registration, you can get "dllunregisterserver" function pointer if (LPFUNC) Lpfunc ();// Perform the registration. Here for simplicity, there is no judgment return value:: FreeLibrary (hDLL);}::setcurrentdirectory (Szworkpath);//Switch back to the original process working directory
In most cases, the above example simplifies the section of code that switches to the working directory. However, if the component is loaded and it needs to load some DLLs that must be dependent on it at the same time, it is possible that the BUG in its own program will cause it to be incorrectly located. Cough...... or let us write the program, to make up for its mistakes ... Who makes us a good person, who makes our level higher than him, who let us on the Vckbase is a "runner" it ...
Four, about component calls
In general, the calling component program probably has the following methods:
#include method |
After IDL is compiled, xxx.h and XXX_I.C files are generated to facilitate the use of C + + programmers. We are so happy that we can use the Direct # # |
#import method |
A more general approach, VC will help us generate packaging classes, make our call more convenient |
Load type library wrapper class method |
If the component provides a IDispatch interface, calling the component in this way is the simplest. But I haven't spoken IDispatch, I can only read the future articles. |
Loading ActiveX wrapper class methods |
The ActiveX hasn't been introduced yet. |
After downloading the sample program, please browse through the usage method:
Example |
Method |
Brief description |
1 |
#include |
Using the most basic API method to call the component, so that everyone familiar with the invocation principle |
2 |
#include |
Most use the API to simplify the use of strings using CComBSTR |
3 |
#include |
How to use the smart pointer ccomptr<> |
4 |
#include |
Show how smart pointers are used for ccomptr<> and ccomqiptr<> blending |
5 |
#include |
How to use the smart pointer ccomqiptr<> |
6 |
#include |
Show how smart pointers are released |
7 |
#import |
The use and exception handling of smart pointers ixxxptr, _bstr_t, _variant_t in VC packaging |
8 |
#import |
How to use namespaces after import |
Comments are written in the sample program, and readers are asked to read them carefully and refer to the MSDN function descriptions at the same time. Here, let me introduce you to the "Smart pointer":
It is cumbersome to manipulate the original interface pointers, and we need to control our own reference counts, API calls, exception handling. ATL then provided 2 smart pointers to the template wrapper classes,ccomptr<> and Ccomqiptr<>, and these two classes were declared in. Ccomqiptr<> contains all the features of the ccomptr<>, so we can use the Smart interface pointer entirely with ccomqiptr<>, and the only thing to illustrate is:ccomqiptr<> Because of the overloaded functionality of the operator, it automatically calls the QueryInterface () function, so the only disadvantage of ccomqiptr<> is that the IUnknown * pointer cannot be defined.
Intelligent pointer Smart pointer, in accordance with the Hungarian nomenclature, typically starts with an SP to represent variable types CComPtr < IUnknown > spunk;//correct//Assuming Ifun is an interface type CComPtr < Ifun & Gt spfun;//correct ccomqiptr < ifun > spfun;//correct ccomqiptr < Ifun, &iid_ifun > spfun;//correct ccomqiptr < IUnknown > spunk;//Error! CComQIPtr cannot define IUnknown pointer
To assign a value to a smart pointer:
CComQIPtr < Ifun > spfun;//call constructor, there is no assignment, the wrapped internal interface pointer is nullccomqiptr < Ifun > Spfun (potherinterface);//Call constructor , the internal interface pointer is assigned a value of//Ifun interface pointer called QueryInterface () obtained by potherinterface This common interface pointer ccomqiptr < Ifun > Spfun (spotherinterface) ; Call the constructor, the internal interface pointer is assigned a value of//through Spotherinterface This can only interface pointer call QueryInterface () Get Ifun interface pointer ccomqiptr < Ifun > Spfun (punknown );//Call constructor, get Ifun interface pointer by IUnknown's QueryInterface () CComQIPtr < ifun > spfun = potherinterface;//= operator overload, The meaning is the same as above Spfun = spotherinterface;//Ibid. spfun = punknown;//Ibid. punknown->queryinterface (Iid_ifun, &SP);// You can also assign a value by QueryInterface//smart pointer, you can use the conditional statement to determine whether the valid if (Spfun) {}//If the pointer is valid if (NULL! = spfun) {}//If the pointer is valid if (!spfun) {}//If the reference Invalid pin if (NULL = = Spfun) {}//If pointer is invalid
The method by which a smart pointer invokes a function:
Spfun.cocreateinstance (...); /equivalence with API functions:: CoCreateInstance (...) Spfun.queryinterface (...); /equivalence with API functions:: QueryInterface () Spfun->add (...); /Call the interface function of the internal interface pointer//call the internal interface pointer of the QueryInterface () function, actually the effect and spfun.queryinterface (...) like spfun->queryinterface (...); Spfun.release ();//Release the internal interface pointer while the internal pointer is assigned a value of nullspfun->release ();//Wrong!!! You must not use it this way. Because this call does not empty the internal pointer, the destructor is released again (two releases)
Cough...... Do not say, do not say, we read more, read more msnd, see the sample program it. Tired of writing:-(
V. Summary
Stay tuned for COM component design and Applications (eight)------How to increase the second interface in an ATL component
Note 1: Compile the proxy/stub, vc6.0, and we'll introduce the "out-of-process components" and "Remote Components" later in this article. Under Vc.net 2003, it's simpler because the proxy/stub is automatically added to our solution as a separate project.
"Reprint" COM Component design and application (vii)--compile, register, invoke