First, in the foreword, we wrote the first COM component program with ATL. This time, mainly introduces compilation, registration, and calling methods. Sample program have you been downloaded? If you haven't downloaded, users of VC6.0 are here, VC.NET's users click here. Second, about compilation 2-1 Lowest dependent "Minimum dependence", indicating that the compiler will static connection to some of the functions you must use in the ATL to the target program. Such the target file size is slightly large, but the independence is stronger, the installation is convenient; if the system is executed, there is a support for ATL.DLL files. How to choose to set it to "Minimum dependence"? The answer is: Delete the predefined macro "_tl_dll", see Figure 1, Figure II. Figure 1, in VC6.0, set method Figure 2, in VC.NET 2003, setting method 2-2 CRT library If you call the runtime library function of CRT in the ATL component program, such as open square SQRT (), So compilation, you may report an error "Error LNK2001: Unresolved External Symbol _main". How to do? Delete a predefined macro "_ATL_MIN_CRT"! That is also shown in the operation method, Figure 2. (This item at VC.NET 2003 is called "Small Use CRT" in ATL ") 2-3 MBCS / Unicode This does not say more, in the predefined macro, using _mbCS or _Unicode, respectively. 2-4 IDL Compilation COM sets a goal: you have to achieve a cross-language call. Since it is a cross-language, then the component's interface description must be able to know in any language environment. How to do? Use .h file description? ------ C language programmer laughs, it is very convenient! Basic programmer cried :-( So Microsoft uses a new file format --- idl file (interface definition description language) .IDL is a text file, its language syntax is simple, very like C. Specific IDL file Explain, see the next time "COM component design and application (8) added new interface". IDL is compiled, generating binary equivalence library file TLB is provided to other languages. Figure 3 intends to compile ATL COM program compilation Process: Figure 3, ATL Component Program Compilation Process Description 1: After compiling, the type library exists in the form of TLB files, but also saves the resources of the target file. Therefore, we will introduce the type library in #import in the future, You can specify a TLB file or you can specify a target file; After compiling, generate a proxy / stub source program, with: DLLDATA.C, XXX_P.C, XXXPS.DEF, XXXPS.mak, we can compile NMAKE.EXE to generate a real agent / stub DLL target file (Note 1). Third, about registration 1: When we use the ATL to write component programs, registration does not have to be responsible. After the compilation is successful, the IDE will help us register; Whether it is a COM component, so it will not help us register. At this time, we can perform menu "Tools / Register Control" to register.
Situation 3: When we write an Exe program with a COM function, the registration method is to run this program; case 4: When we need to use the component program provided by a third party, you can order the "Regsvr32.exe file name" To register. By the way, the way to register is "Regsvr32.exe / U file name"; the case 5: When we need to perform registration in the program (such as installer), then: typedef hresult (WinAPI * FREG) ();
Tchar SzworkPath [MAX_PATH];
:: getCurrentDirectory (SizeOf (SzworkPath); / / Save the current process's work directory
:: SetCurrentDirectory (component catalog); / / Switch to the component's directory
HModule HDLL = :: loadLibrary; // Dynamic loading components
IF (HDLL)
{
FREG LPFUNC = (FREG) :: getProcaddress (HDLL, _T ("DllRegisterServer")); // get registration function pointer
// If it is a reverse registration, you can get the "DLLUNREGISTERSERVER" function pointer
IF (lpfunc) lpfunc (); // executes registration. Here is simple, no judgment returning value
:: Freelibrary (HDLL);
}
:: setCurrentDirectory (SzWorkPath); / / Switch back to the original process work directory
The above example can simplify the code portion of the switching work directory in most cases. However, if this component is loaded, it needs to simultaneously load some DLLs that must be rely on, it is possible that it cannot be properly positioned because of its own program. Cough ... still let us write the program to make up for its mistake ... Who let us be a good person, who makes our level than him, who let us
VCKBASE is a "list" ......
four,
Regarding the total component call, the calling component program has probably the following method:
The #include method IDL is compiled, and the use of the C / C programmer will generate XXX.H and XXX_I.C files. We are really happy. After direct #include, you can use the #import method to relatively generally, the VC will help us generate the packaging class, so that our call is more convenient to load the type library package class method If the component provides the IDispatch interface, this method Calling components is the easiest. However, I didn't talk about Idispatch, I can only look at the article after loading the ActiveX packaging method ActiveX hasn't introduced it, I will say it later.
After downloading the sample program, please browse one by item:
Example method brief description 1 # include completely calls the component with the most basic API mode, so that everyone is familiar with the principle of call 2 # include Using the API mode, use CCOMBSTR to simplify the use of the string 3 # include display smart pointer ccomptr <> Method 4 # include display smart pointer ccomptr <> and ccomqiptr <> mixed usage 5 # include display smart pointer ccomqiptr <> Understand 6 # include Show smart pointer release method 7 # importvc package smart pointer IXXXPTR, _BSTR_T, _Variant_t How to use the use of exception processing 8 # Importimport after the namespace
There are comments in the sample program. Please read the MSDN's function description at the same time. Here, I will introduce you to the "smart pointer": It is more troublesome to operate the original interface pointer. We need our own control reference count, API call, exception handling. So ATL provides 2 intelligent pointers template packages, ccomptr <> and ccomqiptr <>, which are declared in
CComptr
/ / Suppose ifun is an interface type
CComptr
CCOMQIPTR
CCOMQiptr
CCOMQIPTR
CCOMQIPTR
CCOMQIPTR
/ / Call QueryInterface () get the IFUN interface pointer by Potherinterface this normal interface pointer
CCOMQIPTR
// This IFUN interface pointer that only interface pointer () passed by SpotherInterface
CCOMQIPTR
CCOMQIPTR
SPFUN = SpotherInterface; //
SPFUN = punknown; //
Punknown-> queryinterface (IID_IFUN, & SP); // can also be assigned via queryinterface
// After the intelligent pointer assignment, you can use the conditional statement to determine if it is legal and effective.
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 smart pointer, the function is used:
SPFUN.COCREATEINSTANCE (...); // Equivalent with API functions :: cocreateInstance (...) spfun.queryinterface (...); // Equivalent with API functions :: queryinterface ()
SPFUN-> Add (...); // Call the interface function of the internal interface pointer
// Call the queryinterface () function of the internal interface pointer, actually the same as spfun.queryinterface (...)
SPFUN-> queryinterface (...);
SPFun.release (); // Release the internal interface pointer, and the internal pointer is NULL
SPFUN-> Release (); // Wrong! ! ! Don't use it so much.
// Because this call does not empty the internal pointer, then it will be released again (released twice) cough ... do not say, don't say, everyone read the book, see Msnd, Look at the sample program. Write tired :-(
Five, small knot
Please pay attention to "COM component design and application (eight)" ------ How to add a second interface in the ATL component
Note 1: Compile Agent / Stub, VC6.0 is slightly troublesome, and we introduce "Process Extractions" and "Remote Components" later. In VC.NET 2003, it is relatively simple because the agent / stub is automatically added to our solution as a separate project.