DLL Tutorial For Beginners
I was trying to learn DLLs and nothing was really explaining anything; it was just code for you to look at and wonder what was going on. For this article, I assume you know how to use the features of your compiler, such as setting directory paths and such.
To set up the project, select Win32 Console Application, and on the advanced tab, select DLL and empty project options. DLLs are not as hard as you might think they are. First, make your header file; call this DLLTutorial.h. This file is like any other header file in that it has function prototypes.
#ifndef _DLL_TUTORIAL_H_
#define _DLL_TUTORIAL_H_
#include <iostream>
#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
extern "C"
{
DECLDIR int Add( int a, int b );
DECLDIR void Function( void );
}
#endif
The first two lines instruct the compiler to include this file only once. The extern "C" tells the compiler that it is okay to use this in C or C++.
There are two ways of exporting functions in VC++:
- Use __declspec, a Microsoft-specific keyword.
- Create a Module-Definition File (.DEF). The first way is a tad bit easier to do than the second, but both work just fine.
__declspec(dllexport) exports the function symbols to a storage class in your DLL. I defined DECLDIR to do this function when the line
#define DLL_EXPORT
is defined, but also import the functions if the line
#define DLL_EXPORT
is not present in the source file(s). In this case, you will export the functions Add(int a, int b) and Function().
Now, you need to make a source file that you'll call DLLTutorial.cpp.
#include <iostream>
#include "DLL_Tutorial.h"
#define DLL_EXPORT
extern "C"
{
DECLDIR int Add( int a, int b )
{
return( a + b );
}
DECLDIR void Function( void )
{
std::cout << "DLL Called!" << std::endl;
}
}
This is where you define all of your functions. Int Add(int a, int b) simply adds two numbers and void Function(void) just informs you that your DLL was called.
Before I show you how to use the DLL, I want to tell you about the Module-Definition File (.def).
Module-Definition File (.def)
A module definition file is a text file with a .def extension. It is used to export the functions of a DLL, much like __declspec(dllexport), but the .def file is not Microsoft specific. There are only two required sections in a .def file: LIBRARY and EXPORTS. Take a look at a basic .def file and then I'll explain.
LIBRARY dll_tutorial DESCRIPTION "our simple DLL" EXPORTS Add @1 Function @2
The first line, 'LIBRARY', is one of the required sections. This tells the linker what to name your DLL. The next section labeled 'DESCRIPTION' is not required, but I like to put it in. It writes the string into the .rdata [from MSDN] and it tells people who might use the DLL what it does or what it's for. The next section labeled 'EXPORTS' is the other required section; this section makes the functions available to other applications and it creates an import library. When you build the project, not only is a .dll file produced, but an export library is produced with the extension .lib. In addition to the previous sections, there also are four other sections labeled NAME, STACKSIZE, SECTIONS, and VERSION. I will not cover these in this tutorial. but if you search the Internet, I think you'll find something. One more thing: A semicolon (;) starts a comment, as '//' does in C++.
Now that you have created your DLL, you need to learn how to use it in an application. When the DLL was built, it created a .dll file and a .lib file; you will need both.
Implicit Linking
There are two ways to load a DLL; one way is the easy route and the other is more complicated. The easy route is just linking to your .lib file and putting the .dll file in your new projects path. So, create a new Empty Win32 Console project and add a source file. Put the DLL you made in the same directory as your new project.
#include <iostream>
#include <DLLTutorial.h>
int main()
{
Function();
std::cout << Add(32, 58) << "\n";
return(1);
}
You must link to the DLLTutorial.lib file. I did it in Project Settings, but you could use
#pragma comment(lib, "DLLTutorial.lib")
instead. Please note that I set the compiler to look into my DLL folder for the .lib file and set it to look in the directory for the DLL header. If you don't want to do this, you can always put them in the directory with your new project and use "" (quotes) instead of <>. That's how you load a DLL the easy way.
Explicit Linking
The harder way to load a DLL is a little bit more complicated. You will need function pointers and some Windows functions. But, by loading DLLs this way, you do not need the .lib or the header file for the DLL, only the DLL. I'll list some code and then explain it.
#include <iostream>
#include <windows.h>
typedef int (*AddFunc)(int,int);
typedef void (*FunctionFunc)();
int main()
{
AddFunc _AddFunc;
FunctionFunc _FunctionFunc;
HINSTANCE hInstLibrary = LoadLibrary("DLL_Tutorial.dll");
if (hInstLibrary)
{
_AddFunc = (AddFunc)GetProcAddress(hInstLibrary, "Add");
_FunctionFunc = (FunctionFunc)GetProcAddress(hInstLibrary,
"Function");
if (_AddFunc)
{
std::cout << "23 = 43 = " << _AddFunc(23, 43) << std::endl;
}
if (_FunctionFunc)
{
_FunctionFunc();
}
FreeLibrary(hInstLibrary);
}
else
{
std::cout << "DLL Failed To Load!" << std::endl;
}
std::cin.get();
return 0;
}
The first thing you'll notice is that you included the file "windows.h" and removed "DLL_Tutorial.h". The reason is simply because Windows.h contains many Windows functions and you will need only a few right now. It also contains some Windows-specific variables that you will use. You can remove the DLL's header file (DLL_Tutorial.h) because, as I've stated before, you don't need it when you load DLLs this way.
The next thing you'll notice is an odd-looking piece of code in the form of:
typedef int (*AddFunc)(int,int); typedef void (*FunctionFunc)();
Those are function pointers. Because this is a tutorial about DLLs, an in-depth look at function pointers is out of the scope of this tutorial; so, for now just think of them as aliases for the functions the DLL contains. I like to name them with the word "Func" attached on the end. The (int,int) part is the parameters that the function takes; for example, the Add function takes in two ints; therefore, you need those as the parameters for the function pointer. The Function function takes no parameters, so you can leave that blank. The first two lines in main() are the function pointers being declared so that you can set them equal to the functions inside the DLL. I just like to define them beforehand.
An HINSTANCE is a Windows dat type that is a handle to an instance; in this case, that instance will be the DLL. You get the instance of the DLL by using the LoadLibrary() function; it takes in a name as the parameter. After the call to LoadLibrary, you must check to see whether the function succeeded. You can do so by checking whether the HINSTANCE is equal to NULL (defined as 0 in Windows.h or one of the headers Windows.h includes). If it is equal to NULL, the handle is not valid, and you must free the library. In other words, you must free up the memory that the DLL was taking up. If the function succeeded, your HINSTANCE contains the handle to the DLL.
Once you have the handle to the DLL, you now can retrieve the functions from the DLL. To do that, you must use the GetProcAddress() function, which takes in as parameters the handle to the DLL (you can use the HINSTANCE) and the name of the function. You set the function pointers to contain the value returned by GetProcAddress() and you must cast GetProcAddress() to the function pointer that you defined for that function. For example, for the Add() function, you must cast GetProcAddress() to AddFunc; this is so that it knows the parameters and return type. Now, it would be wise to make sure that the function pointers are not equal to NULL and that they hold the functions of the DLL. That is just a simple if statement; if one of them does equal NULL, you must free the library as mentioned above.
Now that the function pointers hold the functions of the DLL, you can use them, but there is one catch: You cannot use the actual function name; you must use the function pointer to call them. After that, all you need to do is free the library and that's it.
Now you know the basics of DLLs. You know how to create them, and you know how to link them with two different methods. There is still more to learn about this, but I'll leave that to you to look for and for better writers to write.

Comments
Userful artical
Posted by vishnu on 04/13/2012 07:18pmI am beginner in C++ and this for me.
ReplyGreat article
Posted by patil on 04/13/2012 07:01amI was searching for methods to export functions from DLL and usage of GetProcAddress. This article really helped. Keep writing such articles :)
ReplyAmazing,
Posted by Fredbobbert on 07/04/2011 03:10amThanks SO much. I have been trying to learn how to create and call a DLL for a while. All the other guides are so complicated and attempt at doing "Fancy" things that a newbie like me can't make any sense of it. Your guide shows me how to use the basics so that I can replace simple functions with what I need my DLL's to perform. Once again, thank you. Keep up the good tutorials.
ReplyYellowFrog
Posted by yellowfrog on 02/09/2010 05:43pmthanks. but got error.
Posted by quantcook on 02/08/2010 01:23pmerror C2491: 'Add' : definition of dllimport function not allowed error C2491: 'Function' : definition of dllimport function not allowed could anyone help on that?
-
ReplySame error
Posted by Melanie on 04/23/2012 04:12amDid you solve this?
-
Replydllexport
Posted by Christian on 04/28/2012 01:15amprobably because in DLLTutorial.cpp: #include "DLL_Tutorial.h" #define DLL_EXPORT should be changed to #define DLL_EXPORT #include "DLL_Tutorial.h" if you don't do that, DLL_Tutorial.h will not declare dllexport but dllimport
ReplyFunction not found!
Posted by RawBits on 03/02/2009 01:32pmHi Masters of the language c++! I'm trying to make a simple dll and a teszt app for start in learning dll with the free borland c++ tools. The problem is that I have trying to do this about 2 week now and no success. Tryed several methods and nothing. Also I tryed to copy past this example but it's the same as the others. I try to explicitly load the dll - without the lib file. But it isn't find any of my exported functions. I generate a map file to get some info and it always has the function but it has 0 for address. Really it's no matter if i use the __declspec(dllexport) or the __export or the .def file it's the same resoult... Please help me!
-
Reply:)
Posted by RawBits on 03/02/2009 01:59pmI think i've got Turex from this ****, but the problem was in all cases that the compiler given the name @IncX$qi instead of my IncX... I just can't imagine why. I used impdef to extract the export information from my dll and it used this name so I inserted this to GetProcAddress and voila! The new questin is: Why???
ReplyHelp PLease
Posted by varundua on 12/21/2008 11:40amTHANK You, perfect article.
Posted by Cy_ on 04/29/2008 02:50pmreally nice..
Posted by Ali Imran on 07/14/2007 06:20amA very good document. I consider the "Implicit Linking" as wrong use of DLL, besst is Explicit. thanks
Replynice for learner
Posted by nasaganesh2002@gmail.com on 06/20/2007 02:36amLoading, Please Wait ...