Chinaunix首页 | 论坛 | 博客
  • 博客访问: 292684
  • 博文数量: 55
  • 博客积分: 2545
  • 博客等级: 少校
  • 技术积分: 937
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-10 06:51
文章分类

全部博文(55)

文章存档

2012年(1)

2011年(2)

2010年(6)

2009年(18)

2008年(28)

我的朋友

分类:

2008-09-30 23:43:55

How to write DLLs using Visual C++

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++.

What is linking?

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.

Static Linking

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.

Dynamic Linking

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.

What are DLLs?

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.

Advantages of using DLLs:

DLLs have several compelling advantages to offer. You will want to write DLLs for your applications for these advantages.

  1. Code Sharing: You will want to write DLLs for your application for this alone. This is why the whole concept is invented, i suppose. Suppose, your 3 applications require the same kind of dialog boxes to take input or some database functions, then you can create a DLL to handle all these common tasks. Once the DLL is debugged and optimized then any of your applications can use it.
  2. Efficient use of system resources: You know in static linking the function code is copied right into the executable. So suppose your 3 applications use same statically linked functions. This not only increases the size of your application but same function code lives 3 times in different address spaces. If you write a DLL containing these common functions. Your applications size is reduces dynamically. And once the DLL is loaded in memory any applications can link to it dynamically without having to reload entire DLL. This saves a lot of memory.
  3. Modular Development: Application development has become modular, nowadays. That means different modules are developed by different individuals or groups. DLLs increase the modularity of application development . DLLs can be written by different individuals or groups and can be assembled at release time.
  4. Plug-in development: If your applications uses DLLs then Plug-ins can be developed for your application which are DLLs themselves. And functionality of your application can be extended without having to reinstall the entire application.
  5. Easy Debugging
  6. Easy Bug Fixing
  7. Easy upgrades

How System Manages DLLs in memory?

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.

How to write DLLs?

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:-

  1. Creating a project: Start Visual C++ and create a new Win32 DLL project.
  2. Write functions in .c or .cpp modules: Write whatever functions you want to export i.e. want other applications to access them. Remember DLLs have no main() or WinMain() function. DLLs do have a special function called DllMain() which is called when the DLL is loaded, unloaded, etc. Check out the documentation on how to use this function. Cause i don't want to repeat things which are already there, in the documentation. Don't forget to declare all the functions that you want to export in a header file. You will want to supply this header file with your DLL to client of your DLL. So that he can compile his programs that use you DLL without any problem. Be careful with .cpp files because they tell compiler that file is in C++ and compiler mangles the functions names, because it has to support function overloading. To prevent, the compiler from mangling the function names add 'extern "C"' in front of declarations and definitions of the functions.
  3. Export functions using .DEF file: Although, functions can be exported from the DLL in many ways. I prefer to use the .DEF file because this is somewhat portable across different compilers. .DEF file is definition file. This file contains information, used by the linker, about a module such as a DLL or an Executable. Linker exports the functions that it sees in the EXPORTS section of the .DEF file. So create an EXPORTS section in the .DEF file and list all the function names that you want to export in this sectionAll other functions will be . private to the DLL and will not be accessible from outsidebuild the project and you . Now, are donefunctions listed in the . The compiler will create a DLL and export whatever EXPORTS section.

Source Code

Although, you can write DLLs using the above information. Some sample source code may brighten up your day. So here it is.

  1. : This contains a Visual C++ DLL project. The DLL exports a simple function written in C. Test project for the DLL is also included which uses the DLL. So that you will get an idea of how to use DLLs.
  2. : Same as above but the function is written in C++.
阅读(499) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~