Please explain a DLL to me?

I've programmed in a few languages - JavaScript, PHP, and a proprietary language called GML used for the Game Maker program - but am new to C++ and have been teaching myself. I'm interested in making a DLL. I understand the fundamentals of Structured programming in C++ and how to make a very simple class. I'm working my way through a textbook a friend let me borrow, but I don't believe that the book covers DLLs.

What I would like to do is show you the code Dev-C++ gives me when I make a new DLL project and ask that someone explain the various parts I'm fuzzy on.

The generic header file dll.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
01- #ifndef _DLL_H_
02- #define _DLL_H_
03- 
04- #if BUILDING_DLL
05- # define DLLIMPORT __declspec (dllexport)
06- #else /* Not BUILDING_DLL */
07- # define DLLIMPORT __declspec (dllimport)
08- #endif /* Not BUILDING_DLL */
09- 
10- 
11- class DLLIMPORT DllClass
12- {
13-   public:
14-     DllClass();
15-     virtual ~DllClass(void);
16- 
17-   private:
18- 
19- };
20- 
21- 
22- #endif /* _DLL_H_ */ 


I understand that lines 1, 2, & 22 state that the header is only to be included if another file has not already included it. I also know lines 11-19 define the class that will hold the DLL's functions and data members.

However, what do lines 4-8 do? What does "DLLIMPORT" between the class statement and the class name on line 11 do?

Now in the source file dllmain.cpp it gives me

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
01- /* Replace "dll.h" with the name of your header */
02- #include "dll.h"
03- #include <windows.h>
04- 
05- DllClass::DllClass()
06- {
07- 
08- }
09- 
10- 
11- DllClass::~DllClass ()
12- {
13- 
14- }
15- 
16- 
17- BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
18-                        DWORD reason        /* Reason this function is being called. */ ,
19-                        LPVOID reserved     /* Not used. */ )
20- {
21-     switch (reason)
22-     {
23-       case DLL_PROCESS_ATTACH:
24-         break;
25- 
26-       case DLL_PROCESS_DETACH:
27-         break;
28- 
29-       case DLL_THREAD_ATTACH:
30-         break;
31- 
32-       case DLL_THREAD_DETACH:
33-         break;
34-     }
35- 
36-     /* Returns TRUE on success, FALSE on failure */
37-     return TRUE;
38- }


I understand that lines 2-3 include my dll's header file as well as the windows.h header file. I know that 5-14 are the constructor and destructor functions for my class. I know that any other functions would be put before line 17.

However, what do lines 17-38 accomplish? Is there anything specific that needs to be in the (de)constructor functions of a DLL? or are these optional like other classes? Is it necessary to include the windows.h header? What would I possibly put inside the cases of the switch statement (lines 21-34)?

I'm trying to teach myself C++. So if someone can break these things down for me and explain not just what they are but why they are there - what they accomplish, if there are alternatives, etc. - so that I don't just repeat someone else' code, but can actually grasp what I'm doing it would be much appreciated.

Thank you in advance.
However, what do lines 4-8 do? What does "DLLIMPORT" between the class statement and the class name on line 11 do?
They declare macros for the preprocessor. Depending on whether you're building or linking to a DLL, DLLIMPORT will be defined as one of those two.

However, what do lines 17-38 accomplish?
I haven't worked a lot with DLLs, but I believe DllMain() is called when certain things are done with the DLL, such as loading and unloading. You can use it to initialize and uninitialize things if you need to.

Is it necessary to include the windows.h header?
You need it because it defined several things, such as the macros BOOL, APIENTRY, and DLL_PROCESS_ATTACH you're using there.
So with what you've said, and some extra research, I think I understand a little better. So a macro replaces an identifier - like PI - with an expression - 3.14 - and now every time the preprocessor sees PI it replaces it with 3.14?

So if DLLIMPORT is a macro, in that header file I could potentially replace line 11 with

class __declspec (dllexport) DLLClass

And get the same result assuming I'm only exporting the functions not importing? Is this correct?

So if my understanding is correct, Lines 4-8 say "If the constant BUILDING_DLL is true, define DLLIMPORT as __declspec (dllexport) else define DLLIMPORT as __declspec (dllimport)." But where is BUILDING_DLL defined at? Would it be defined as a macro in the calling program?

I also did some research on MSDN and it's saying that __declspec is used to define microsoft specific storage class modifiers? So this means that __declspec (dllexport) is telling C++ these are functions to be used by an external program? what about dllimport?
So if DLLIMPORT is a macro, in that header file I could potentially replace line 11 with

class __declspec (dllexport) DLLClass

And get the same result assuming I'm only exporting the functions not importing? Is this correct?
Exactly.

But where is BUILDING_DLL defined at?
It may be a compiler-defined macro, I'm not sure. You should Google it.
Remember, however, that macros are used before compiling. Once the DLL is built, it doesn't matter whether the program that uses it defines it or not. This is a mistake many people make when they are first introduced to macros.

__declspec(dllexport) tells the linker that that function or class should be exported. In other words, symbol data is kept in the DLL, which allows a program that uses it to find at run time, for example, where the function starts.
Normally, you compile a program into a single executable file (foo.exe on Windows). All the functions and variables you create in the program are directly usable. Define the function here. Call it later anywhere you want.

However, it is often useful to compile a program into multiple parts. An example is the SDL library used for games. The SDL.dll file contains all the functions that create a window and draw images on it. Your program foo.exe uses those function.

The trick, however, is getting the two files to work together. That's what those macros do.

When writing a DLL (such as was done when they wrote the SDL DLL), you want to list certain functions (such as SDL_SetVideoMode()) as being found in the DLL.

However, when writing your EXE (that uses the SDL), you want to list those same functions as being found in SDL.dll and not in your EXE.

The DLLIMPORT macro gives you this power. When compiling the SDL DLLs, they #include "SDL.h" just like you do when compiling your game's EXE. When compiling the DLL, the functions are declared with the 'export' -- the functions are provided and usable by another EXE). When compiling the EXE, the functions are declared with 'import' -- the functions are not provided and must be found elsewhere.

Now, when you run foo.exe, Windows notices that it needs a function named "SDL_SetVideoMode" -- and the function can be found in the file "SDL.dll". If the DLL file is indeed found, Windows loads that file as well, and links all references to "SDL_SetVideoMode" to actually call the function in the DLL. Thereafter the program works properly.

Hope this helps.
Last edited on
So what does SDL.lib do? I assume it calls LoadLibrary() and GetProcAddress(). Am I right?
AH... See now I think I get the whole picture.

When the DLL is being built, your header finds the value BUILDING_DLL = true and the header sets all those functions to export.

When the DLL is being loaded by another program, BUILDING_DLL = false (or maybe just not set?) and so that same header can now be used to import those functions.

Is this correct?
Correct.

The lib file is just a fancy list of functions and where they are found in the DLL, so that you can get the procedure addresses by ordinal.
Awesome. Much thanks to both of you. I think I know what I need to know to proceed from here.

Thanks again.
Topic archived. No new replies allowed.