Foreword
This chapter is to introduce the writing, use, and related topics of dynamic linknotes (DLL) dynamic link. Dynamic chain junction library is an important area for Windows programming. If you don't believe, you can look at those .DLL files in the Windows system directory, its importance and frequency of use can be seen.
Basically, if the VCL software component does not talk, write and use the DLL in C Builder is consistent with the traditional Windows SDK, but such a C Builder will lose its proud The advantage is. So in this chapter I will introduce you how to write a DLL that uses VCL components, but also a comprehensive discussion on matters that should be paid attention to in DLL use between Visual C , VBs.
Write dynamic chain knots (DLL) with C Builder
Figure 1 About Dialog written in C Builder
What is shown in Figure is what I have to write is About Dialog that is combined with VCL components. It seems that it is not a commercial software?
C Builder has a dense design in the visual design in the contextual design. However, in a realistic working environment, maybe in your hand is not written by C Builder, but use other programs such as Visual C , VB or Borland C , if you want to rewrite the original program, not only When you waste, and maybe the boss is not allowed, then what should I do? By the way, it is to use the Way to write a DLL to reach the purpose of the program. In order to allow the traditional Windows SDK programmer to enjoy this advantage, you can complete the part of the visual design part with DLL, and then provide External Chinese is called for others, so you can take into account the two, "to hold both ends, used there", and solve problems smoothly.
All right! Not much nonsense, now start to enter the topic!
Establish a DLL project
Establish a DLL task and general application. Similarly, you can build a new item by [file / new] and select a DLL type.
As shown in Figure 2:
Figure 2 Select DLL Project Type
After you have selected the project type, it automatically generates a relevant file. Unlike the application, it only produces a Project file without including a table file, and the file is just an empty shell containing the DLL enterpoint, the program is approximately as follows:
Int WinAPI DLLENTRYPOINT (Hinstance Hinst, Unsigned Long Reason, Void *)
{
Return 1;
}
DLLENTRYPOINT is a DLL-constant program entry point because there is no processing in this system, so it is directly Return 1.
Join TFORM form
In order to write about Dialog as shown, there is no doubt that we have to join a TForm table because it is not automatically generated when establishing a DLL project, so you have to join. At this point you can [File / New Form] to join a table. Let us use the same way as the general application to add the necessary soft components, as shown in the figure.
Figure TForm in Design Time.
You can see that I use a TPANEL component in the program (except for the marked, there is another platform for placing all components). And a TIMAGE element, the picture of the PAANEL component is different, that is to modify its Bevelinner, Bevelouter, BevelWidth, you can try to modify it, see if you can make a better effect . As for TIMAGE, it is used as a component that displays the Athena graphic. After the position of all components is arranged, we set the onclick event handle of all components, let it turn off the conversation window when the user presses the mouse. This event handles a function of simple, only a short line.
Void __fastcall tform1 :: image1click (TOBJECT * SENDER)
{
CLOSE ();
}
Ok, so I have completed the program that joined the table.
Write an output function (Export Function)
After the design of the completed table, we will write the output function, which can display this form using the call to the form. Our output correspondence is as follows:
Extern "C" void _stdcall showimage (void);
Where Extern "C" is used to tell the compiler, name the C named method, because the C namefind will add the parameter type or other decorative word after the letter name, this will result Other programs such as VC , VB, etc. can't use it. Also __stdcall is used to indicate the parameter incoming method it uses. We will introduce more in-depth in the following two.
Let's come to see the freewheel itself, this card is very simple, just use the new dynamic to generate a table, then use ShowModal to display the table, ShowModal will wait until the user turns off the table after pressing Click, then we will use Delete The instruction is released to release the memory.
Void_export _stdcall showimage (void)
{
Form1 = new TFORM1 (NULL);
FORM1-> ShowModal ();
DELETE FORM1;
}
After completing the above, you can compile the program. At this point C Builder generates a DLL file, which will generate a Dllsamp.dll file in this peripheral, and this is a dynamic chain junction library for external calls.
Use DLL in C Builder
Let me tell you how to use dynamic chain junction libraries. We take the DLL produced in front as an example. There are two ways to use the DLL, respectively, for clear calls and not clear calls.
I will first explain the way you don't clearly call. Uncleary call refers to, in the program, there is no line in the program to load the DLL, but use the link to enter a letter library file (lib) that records the input function, so that the system will automatically The DLL is loaded, and it is released after the use is completed, and it is not necessary to use the user (that is, the call is a function) to load and release the action.
First, a lib file must be generated, you can use implib.exe in the C Builder program to generate this file, do not use Visual C Implib.exe, because Microsoft is used by the format of the Coff format, The format used by Borland is the LIB file in the OMF format. (Similarly, if your LIB file is to give Visual C link, then use it attached to Implib.exe, not in use). Therefore, we can produce a Dllsamp.lib file with the following instructions. Implib Dllsamp.lib Dllsamp.dll
So you can get a DLLSamp.lib file with a row.
Then let's write the example of using the DLL. This program is quite simple, I only put a button in the table, then write the Button's OnClick event handle, make it call the showImage function.
One thing to note is that you must add the previous DLLSAMP.LIB to this item, use the [Project / Add to Project] to select the lib type file, you can add it.
Finally, we can link the program, the following is the result of its execution.
Figure 4 execution result.
Dynamic chain junction library
In the previous example, we have demonstrated a basic DLL writing method. However, it can only be said to be a small part of Know-how, and then I want to make a thorough discussion for the DLL, trying to make you have it A comprehensive cognition, and also hope to tell you some Know-why about the DLL outside Know-how.
DLL life and death
DLL as the name suggests, is a library that can dynamically link. This contains two meaning. First, it is a dynamic link, that is, it must have the basic characteristics of "tricking, swaying", which only be loaded into the system when needed, and is not Although it is released when needed. Second, it is a library, so its behavioral mode and the general library have no difference. When it is loaded, it is considered as other general functions.
"Tricks, swaying" DLL
As we mentioned earlier, the DLL must have the basic characteristics of "tricking, swaying". So how do you load and release the DLL? For this point, we must be divided into two aspects; that is, the so-called clear call and not clear call.
Explicit call: The so-called clear call is to load the DLL using the loadLibrary function. Use the freeelibrary in a Freelibrary letter to release the DLL. This method is to load the DLL by the user to load the DLL through LoadLibrary, then obtain a letterply address in getProcAddress, and then call the form. Finally, after the DLL is not used, it will be released. The advantage of using clear calls is that you can fully control the load and release of the DLL, the most efficient use of system resources: Disadvantages, you must use GetProcAddress to get the use of the letterpit site, but due to the use of getProcAddress To get a letterpoint, there is therefore adding a lot of flexibility to use. Since this use method is active and visible, the name is explicit call.
IMPLICITED LINKED: The so-called unclear call is the purpose of the call function using the output library corresponding to the link DLL library (Export Library). Therefore, the program loaded into the DLL and the release of the DLL is invisible. When the program is loaded with this output library, the system will be loaded, and the system will release the DLL release when the program is used. . The advantage of using an unclear call is that the user can do not have to care about the functional load and release related issues, as used as the general static functions. Since this use method is loaded into a function and is not active and invisible, the name is not explicitly called. Number of uses of DLL (Usage Count)
The load and release mentioned earlier are not clearly defined. why? Because the loading and release of the DLL involves load and release when multi-stroke use. Since the DLL is a dynamic link, there is also a number of programs to use the same DLL, for example: if an x.dll is used by A, B, C, then X.dll will be loaded . However, in order to provide resources, the system is of course not loaded, so there is a table in the system to record the number of times X.dll. So when the A program loads x.dll, the B, C program loads X.DLL again, at this time, X.DLL is not repeatedly loaded, and the system only adds X.DLL usage, and then The previously loaded x.dll address is transmitted back to B, C two programs, so that the purpose of sharing a library can be achieved. Similarly, when the DLL is released, if the DLL is used in many people, the system is purely only the number of usage of the DLL. When the number of uses is equal to 0, the system will "truly" the system Released. Otherwise, if the system is not divided into blue and red soap, it will cause the DLL to cause the system's disaster.
It is known from the above, whether we use clear calls or not clear calls, DLL load and release are related to its number of use. So the life of DLL is related to the death of the Dance. When its number of use is not 0, it means that it is "Yang Shou None", the system will maintain its activity status; contrary, if the number of use is 0 Then, it means that it is "longevity", the system will release it and reclaim the resources used. However, when the DLL is used, the DLL will be "the Soul" in the system because the DLL is not released. This method of managing shared resources is also used in OLE.
Practice of new knowledge
Now we have learned the use of the DLL, there is another way of clear calls, we can modify the previous example to use the DLL using a clear call.
Void (* showimage) (void);
Void __fastcall tform1 :: showbuttonclick (Tobject * Sender)
{
Hinstance hinst;
Hinst = loadingLibrary ("dllsamp.dll");
(FarProc &) ShowImage = GetProcaddress (HinSt, "Showimage");
ShowImage ();
Freelibrary (HINST);
}
The above is a modified program, as the program has changed to a clear call, so it is not necessary to use dllsamp.lib, so there is no problem with the LIB file format used in BCB and VC. Here I simply illustrate several functions used.
Hinst = loadLibrary ("dllsamp.dll") is used to load DLLSAMP.DLL, and return the DLL's Hinstance value, which is based on the Scepter of the DLL. (FarProc &) ShowImage = getProcaddress (HinSt, "Showimage") Use the previous Hinstance value to call GetProcAddress to get the location of the showimage function, because the value sent back by GetProcAddress is FarProc, so we must do a type of conversion. Here I use (FarProc &) to do other conversions in Reference.
Freelibrary (HINST) is used to release the DLL using FreeELibrary.
Enter the standard writing of a function and output functions
As we use in the input of the entered and output, in order to simplify the writing of the program, use Borland's _export compile instructions in order to and 16-bit, here I must point out that this way of writing is non-standard. Writing, in fact, Microsoft uses another definition in the 32-bit prior to use another way of writing, and the writing of the output functions. It is a written method of all the four seas, using _export's oldwind in the like, such as Visual C The compiler cannot be compiled by compile.
In theory, we hope that you can use a single keyword to define an output function, just like _export, but Microsoft uses another keyword in its 32-bit program to define input and output functions. Then, it is __declspec keyword, which can pass two parameters of DLLIMPORT and DLLEXPORT, which are used to represent input fifth and output.
In other words, if you want to write the output function, you must use __declspec (dllexport) to define the file. Vibrant If you want to use the input function, you must use __declspec (dllimport) to define the function.
Therefore, due to the different ways of input and output functions, you must use two different include files to define them. If you don't want to be so troubles, then you must use the gauge definition to achieve a more useful purpose Luo, which is a person who holds an opposition argument, it is simply evil (there is also a huge gathering witch - Macro Woodoo).
Windows's actual master Jeffrey Richter, that is, the author of Advanced Windows suggests that we use the following methods to achieve a multi-purpose effect (also through the giant witch).
#ifndef _showimg_h_
#define _ShowImg_h_
#ifndef imgdll
#define extern __DECLSPEC (DLLIMPORT)
#ELSE
#define extern __DECLSPEC (DLLEXPORT)
#ENDIF
Void Extern showImage (Void);
#ENDIF
In this way, when you write a DLL, you can write a fift:
#define IMGDLL
#include "image.h"
When the user uses the DLL, simply contains image.h directly. This is an inconvenience that is solved using __Declspec (dllimport) and __declspec (dllexport).
Candle is also a DLL letter name
After talking about the standard writing, let us talk about a letter naming principle that is more easier to get. Originally under normal circumstances, we do not need a letter of writing a compiler, because in the case of using the same compiler, there will be no big problems. However, the problem is, because the DLL is a dynamic linking group, so its goal is to make multiple program sharing programs and resources. So if the DLL can only be used for the same compiler, then its use is a big discount. So we still have to understand the name of the letter. At the same time, due to the different compilers in a variety of compilers, we must also understand their differences, and most importantly, we must find out how they communicate. Naming rules for C Builder
In addition to the __declspec compile instructions mentioned earlier, there are still several modes of modes for C Builders to affect the name of the function, they are __cdecl, __ stdcall, __ pascal, __ fastcall four modifies. In order to understand the impact of this modifier for a letter name, we can use the following programs to test:
#ifndef _dllname01_h_
#define _dllname01_h_
#ifndef dllname
#define extern __DECLSPEC (DLLIMPORT)
#ELSE
#define extern __DECLSPEC (DLLEXPORT)
#ENDIF
Extern void dllname01 (void);
EXTERN VOID _STDCALL DLLNAME02 (VOID);
Extern void _cdecl dllname03 (void);
Extern void _pascal dllname04 (void);
Extern void _fastcall dllname05 (void);
}
#ENDIF
The above is the definition of the program, and we can write a corresponding empty function in the .CPP file, then compile it into a DLL file, use TDUMP.EXE or Dumpbin.exe within VC to observe its content, due to TDUMP The letter is named decoded, but it will make the confusing name, so the following output is obtained by dumpbin.exe.
Verifier DLL in DLL Description
Void dllname01 (void) @ dllname01 $ qv because it is a CPP code
void _stdcall dllname02 (void) @ dllname02 $ qsv so the letter name is repaired
Void _cdecl dllname03 (void) @ dllname03 $ qv decorated.
Void _Pascal Dllname04 (Void) @ DLLNAME04 $ qv
void _fastcall dllname05 (void) @ dllname05 $ qqrv
The above results make you twilight two gold steel, you can't touch your hair. This is because our program name is expressed in CPP, C Builder will name the C unique naming method, this name mode will add the nature of the use parameters after the letter name, such as Parameter category, etc. This has a special name in C , called Mangled Name, which is a naming rule issued to make multiple load functions. (Note: Add (int) and add (double) in C can exist at the same time, so you must distinguish between Object Code). At the same time, this naming method is different because of the various compiler manufacturers, so avoid use when writing DLLs. In order to avoid the above problems, we will change the way the following declaration:
#define _dllname01_h_ # ifndef dllname
#define extern __DECLSPEC (DLLIMPORT)
#ELSE
#define extern __DECLSPEC (DLLEXPORT)
#ENDIF
Extern "C" {
Extern void dllname011 (void);
Extern void _stdcall dllname022 (void);
Extern void _cdecl dllname033 (void);
Extern void _pascal dllname044 (void);
Extern void _fastcall dllname055 (void);
}
#ENDIF
Where Extern "C" {琕琕.}; Is used to tell the compiler to use C named: Do not use C mangled name. If there is only one group, you can declare it directly below:
EXTERN "C" void __stdcall showimage ();
Now we can view the letter name after removing mangled name:
Verifier DLL in DLL Description
Void dllname01 (void) _dllname01 name plus bottom line
Void _stdcall dllname02 (void) Dllname02 name is not changed
Void _cdecl dllname03 (void) _dllname03 name plus bottom line
Void _Pascal Dllname04 (Void) Dllname04 name uppercase
void _fastcall dllname05 (void) @ dllname05 name plus @
We can know above that the name when using the _cDecl modifies when not adding the word. _Pascal modified words generated by the word name and the 16-bit standard DLL letter name (which is not accepted in VC ), __ fastcall's word name plus @.
Among them, the most used in Win32 is _stdcall modifies, this is also the modified word you want to write when you can use it together with other languages, followed by __cdecl modifier, which is used to transmit non-parameter type Letters such as Printf, Sprintf, etc. are used. The other two have no chance to use in the DLL.
Conclusion: By it is known that you must pay attention to the following matters when writing a DLL in C Builder:
Use __Declspec (dllimport) and the standard type of __Declspec (dllexport). Note C 's Mangled Name. Pay attention to the use of modified words. Use __stdcall repair unless you use an uncertain parameter
Decoration.
(4) Do not confuse the use of __Declspec and __stdcall. This two has no absolute correlation. Even the program may be planted here, remember, remember!
How, after reading the above introduction, is there a feeling of swaying aware. After understanding the above rules, you should not fall you when you write or use the DLL, you should not fall!
Finally, we are listed in the standard DLL declaration to deepen your impression:
#ifndef _showimg_h_
#define _ShowImg_h_
#ifndef imgdll
#define extern __DECLSPEC (DLLIMPORT)
#ELSE
#define extern __DECLSPEC (DLLEXPORT) #ENDIF
EXTERN "C" extern void __stdcall showimage (void);
#ENDIF
Language Shuangxiong 'C Builder and Visual C
As we have written on the matters that write a DLL on C Builder, let's talk about another focus - C Builder and Visual C links. If you don't use Visual C , you can ignore this part. If you need to use the Visual C DLL or you must provide DLL to VC or VB, you may bring you unexpected gain.
VC uses C Builder DLL Versions
The use of C Builder's DLL in Visual C and the use of Datong in C Builder, only a few things must be noted.
(1) Visual C LIB file format and C Builder's lib format, so you have to re-generate a lib. However, unfortunately, the version of VC did not provide an Implib.exe in the 32-bit version (this has not been made to many people, so you can't make it easy to generate lib files. Solutions There are two: one of them writes an empty DLL function in VC , which makes it generated by LIB files, which is the use of LoadLibrary, GetProcAddress, clear call mode.
(2) Use the standard readings mentioned earlier.
Use VC DLL in C Builder
Note that the special naming rules used by Microsoft in Visual C are used in C Builder. In addition to the few items mentioned earlier in VC , it also uses a special parameter nomenclature. In short, it is the size of the parameter after the function name, this naming method will cause C The troubles of Builder, VB, Delphi use. for example
Extern "C" _Declspec (dllexport) Void __stdcall showimage (void);
The word name generated in VC is showimage @ 0 (where 0 means the parameter size), rather than ShowImage, which is generated in C Builder, this is a VC known issue, this problem has also caused a lot of use NON- The problem of VC users, the solution is to add the following narrative in the DEF file of the DLL
Exports
Showimage = showimage @ 0
This can create the correct written name. If you don't want to modify the DEF file, you can also add the following link guidelines in the program.
#pragma Comment (Linker, "/ Exports: showimage = showimage @ 0))
Suppose you don't sure its correct name, you can use Dumpbin or TDUMP observation.
The above is an additional description for the program of VC . Finally, we call the About Dialog DLL of this unit with a VC program. The key prices of this program are as follows:
Void CvCusedllapp :: onappabout ()
{
Void (* showimage) (void);
Hinstance hinst;
Hinst = loadingLibrary ("dllsamp2.dll");
(FarProc &) ShowImage = GetProcaddress (HinSt, "Showimage");
ShowImage ();
Freelibrary (HINST);
}