Saturday, January 15, 2011

How a dll using in vc++

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 );
}
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++:
  1. Use __declspec, a Microsoft-specific keyword.
  2. 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
#endif
#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.

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;
}