分类:
2008-09-30 23:43:55
DLLs play a vital role in Windows programming. You can see almost all the commercial applications come with their own DLLs. You may also have seen programs crashing down saying, "A required .DLL file, XYZ.DLL, was not found." You may be wondering what these DLLs are. And why programs cannot run without them. You might have figured out yourself that these files are not ordinary for sure. Even Windows operating system comes with its own set of DLLs. e.g. kernel32.dll, user32.dll, etc. In this article we will explore the basics of DLLs and how to write them using Visual C++.
In order to understand what DLLs are, which stands for Dynamic Link Library, you need to understand concept of Linking and Library. If you are a C or C++ programmer then you know what a Library is. A library is a file which contains compiled object code of functions arranged in such a manner that the linker can find exact address of any function contained in the library and resolve the reference to it. Reference is simply a function call to that function. This process of resolving references with actual address of a function in library is called Linking and is generally the last process in compilation. Linking can be of two types Static and Dynamic. We will get an overview of what these both means.
When resolving a reference to a function in the library, function code is copied from the library into executable when the first reference is encountered. All later references to the same function will be resolved with the function code copied into the executable and not the function code in library, for saving space, obviously. Once all the references are resolved, the linker will link with the startup code of the compiler and create an executable. This executable contains all the code of functions in itself and so does not require to link with the library again in order to run. This process is called as Static Linking, because all the references to function calls are resolved at link time.
In Dynamic Linking, unlike Static Linking, references to function calls are not resolved until run-time. So the names of all the functions are put in a special table in executable called function import table. This table contains all the names of functions that need to be linked dynamically and the names of libraries in which the function code lives. When the program runs, the libraries (DLLs), whose names appear in the function import table, are loaded and references to the function calls in the DLL are resolved with the actual address of the function code. As you can see, this process is completely analogous to Dynamic or Late Binding in C++ implemented through virtual functions. Where the program doesn't know which class's function to call until run-time. In Dynamic Linking function code is not copied in the executable, for obvious reasons. So the size of the executable reduces dramatically.
Now that you have all the background information about Linking and how the linker resolves references to function calls, you are ready to understand what the DLLs are. DLLs are simply compiled libraries containing functions, which a program can link to dynamically i.e. at run-time. You may remember this type of linking is called as dynamic because the compiler does not know the exact address of the function in the library at the link time. So it puts the function names that need to be linked dynamically in a special table called function import table. When the program runs the DLL is loaded along with the program and the references are resolved i.e. function calls are replaced with the exact addresses of the functions in memory. To facilitate this type of linking DLLs have a special table called export table, containing names of functions that can be linked to dynamically by other programs or DLLs and their actual addresses, called function export table or simply export table. Only functions that appear in the DLL's export table can be linked to dynamically, all other functions or data are private to the DLL. No external program has access to it. You can see this export table with a simple windows utility called ‘Quick View’. Just right click on any DLL and select ‘Quick View’. It will show what functions the DLL has to offer.
You will be surprised to know that, DLLs or Dynamic Linking is not a new concept introduced in windows. Programmers always wanted to have this kind of facility of Dynamic Linking. But had to do some Ultra-Sophisticated programming for that and there was not support of Operating System for that. Linux has it’s own techniques of Dynamic Linking. You might even have seen some files in the /usr/lib directory named something like libabc.so.1, libxyz.so.3, etc. These files are nothing but Linux’s counterpart of the Windows DLLs. .so extension stands for Shared Object and the digit following that, represents linker that can load and link to these files Dynamically. Dynamic Linking is supported on Linux through a program called ‘ld.so’. How to write these files and use them is out of the scope of this article. Just check you Linux’s online help. You should find detailed information about how to create these Dynamically Linkable files.
DLLs have several compelling advantages to offer. You will want to write DLLs for your applications for these advantages.
You know how the system loads the DLLs, a program uses, recursively. System first loads the program and looks for the DLL names in the program's import list. It then checks whether the DLL specified in import list is already loaded in memory by other application. If it is already present in memory then references are resolved with the same instance of the DLL, obviously. After all, this is the key advantage, DLLs offer. If the DLL is not already present in memory a fresh instance is loaded and references are resolved with this newly created instance. All later references to the function calls will be resolved with this instance. Until the DLL is not unloaded.
But how does the system know when to unload a DLL from memory. If it just unloaded the DLL from memory with the program which loaded it, other programs which linked later to the same instance of the DLL would crash because the DLL is no more present in memory. Then how does the system takes care of this. System simply associates a counter with every instance of DLL, it loads. The counter is incremented by 1 every time a new program links to the same DLL and is decremented by 1 when a linked program terminates. When this counter becomes 0 the system can safely unload the DLL from memory. e.g. We have 3 programs foo1.exe, foo2.exe, foo3.exe. All the three programs use some functions in bar.dll. Now, the user first runs foo1.exe with which a fresh instance of bar.dll is loaded in memory and the counter associated with DLL, which was initially 0, is incremented by 1 so it becomes 1 now. While the foo1.exe is doing something foo2.exe and foo3.exe are executed by user. As bar.dll is already present in memory the system links foo2.exe and foo3.exe with the same instance of bar.dll and the counter becomes 3. Because, two programs(foo2.exe, foo3.exe) are linked with the same instance of bar.dll, the counter is incremented by 1, twice. Now the foo1.exe finishes and is unloaded from memory but the system does not unload the DLL from memory because the counter is 2 now (is decremented by 1). After some time, foo3.exe finishes and is kicked out from memory decrementing the counter by 1 so it becomes 1 now. After that, foo2.exe finishes and the counter is decremented by 1 making it 0. As the counter is 0, the system knows DLL is not needed any more by any programs. So it kicks out the DLL out of memory.
At last, the most awaited section, 'How to write a DLL?', is here. You might have got bored with the above information and feeling that all i wanted was some simple example about how to write a DLL. But all the theoretical part was more important than actually writing DLL.Once you know the theoretical part, writing DLL becomes a child's play. If you don't know what is Dynamic Linking or Linking then everything else you know about DLLs is sheer waste. Anyway, without boring you any more let us proceed with actually writing DLL.
Although DLLs can be written in a variety of languages viz. Fortran, Pascal, Assembly, etc, We will be focusing on writing DLLs using Visual C++. Because most of the windows development is done in Visual C++. Thus, the task of writing DLLs can be divided in three major tasks, as follows:-
Although, you can write DLLs using the above information. Some sample source code may brighten up your day. So here it is.