Regular DLL Tutor For Beginners
By King Coffee
http://www.codeproject.com/dll/RegDLL.asp
Introduction
This article shows you how to create a Win32 and MFC DLL to dynamically link a Library to your application. Microsoft Foundation Class (MFC) library can be used to create simplified DLLs. The MFC supports two types of DLLs, regular and extension:
Win32 DLL (non-MFC Library based) in general, only supports regular DLLs. You should use Win32 DLLs when your DLL is not using the MFC Library, Win32 is substantially more efficient.
Extension DLLs are for developing re-useable binary code and it is for advance usage (such as ATL and COM). DLLs are very useful, especially if you want to create programs that are modular. You can go to the Microsoft MSDN web page if you want to know more on DLLs.
This tutorial is in five parts. It gives a step by step procedure for developing a Win32 DLL and a regular MFC DLL object. There are three client applications, two Win32 console applications (one for Load Time linkage and the other illustrates Run Time linkage), the third DLL client application uses the shared MFC Library.
Regular DLLs execute in the same memory space as the DLL client application, you don't have to worry about marshaling data and pointers across process boundaries.
Part One, The Win32 DLL Object
First, we are going to make the Win32 DLL core files for the project, W32DLL.xxx.
Next, we are going to make the DLL declaration/header file: DLLCode.h. Select New from the file menu, then select "C/C++ Header File" and name the file DLLCode. Click OK.
Copy and paste the following code excerpt:
<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="preimg0" style="WIDTH: 6.75pt; HEIGHT: 6.75pt" alt="" type="#_x0000_t75" o:spid="_x0000_i1026"><imagedata o:href="http://www.codeproject.com/images/minus.gif" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.gif"></imagedata></shape>Collapse
/*******************************************************
File name: DLLCode.h
This file contains all the DLL interfacing object
declarations, in this example:
a class object, two global function object, and
a global integer variable.
Notice: we use the same header file for compiling the
.DLL and the .exe (application).
This header file defines a macro which export the target
DLL objects if we are building
a DLL, otherwise it import the DLL objects into an
application which uses the DLL. If
we define DLLDIR_EX (a preprocessor identifier),
then the preprocessor define macro
DLLDIR (a mnemonic for DLL import/export Direction)
becomes an export instruction,
otherwise its an import instruction by default.
************************************************************/
#ifdef DLLDIR_EX
#define DLLDIR __declspec(dllexport) // export DLL information
#else
#define DLLDIR __declspec(dllimport) // import DLL information
#endif
// The extern "C" declaration allows mixed languages compactability,
// it prevents the C++ compiler from using decorated (modified)
// names for the functions
extern "C" {
void DLLDIR DLLfun1(char*);
int DLLDIR DLLfun2(int);
};
extern int DLLDIR DLLArg;
class DLLDIR DLLclass
{
public:
DLLclass(); // Class Constructor
~DLLclass(); // Class destructor
int Add(int, int); // Class function Add
int Sub(int, int); // Class function Subtract
int Arg; // Warning: you should not
// import class variables
// since the DLL object can be dynamically unloaded.
};
Save and close this header file. Now we are going to create the DLL implementation file, DLLCode.cpp.
Select New from the file menu, then select "C++ Source File" and name the file DLLCode. Then click OK.
Copy and paste the following code excerpt:
/*********************************************************
File name: DLLCode.cpp
The header file, DLLCode.h, prototypes
all of the DLL interface objects
**********************************************************/
#include "Stdafx.h"
#include "DLLCode.h"
#include <iostream>
using namespace std;
void DLLfun1(char* a)
{
cout << a << endl;
};
int DLLfun2(int a) { return a<<1; };
int DLLArg = 100;
DLLclass::DLLclass() {};
DLLclass::~DLLclass() {};
int DLLclass::Add(int a, int b)
{
return a + b;
};
int DLLclass::Sub(int a, int b)
{
return a - b;
};
We want to access the DLL, so we need to export it. When the DLL is built, it also builds something called an export library. The export library is similar to a regular library. It contains all of the information necessary to dynamically link to the DLL at runtime. When we export a function or a class, the function name and location is stored in the export library. The application uses the DLL links in the export library to access the DLL.
To create the DLL export library, select "setting..." from the Project menu. Select the C/C++ tab. Append, or insert, ",DLLDIR_EX" (without the quotation marks) to the Preprocessor Definition text box. Then click OK. This will prevent compiler assumptions and warnings.
Note, Visual C++ defines an export macro <projectname>_EXPORTS, in our case, W32DLL_EXPORTS. But we used DLLDIR_EX, a generic macro name.
Click the "!" button to compile, build, and run the W32DLL project.
Close the "Executable For Debug Session" dialog box, we ran the DLL prematurely.
Congratulation, you finished building the Win32 DLL and its export Library.
Part Two, DLL Client Application One
This is the simplest and most versatile DLL Client, without MFC. This flexibility is due to the DLL export library information.
Now, we are going to make a Win32 console application, project DLLClient1. In this application, the DLL is loaded at application startup, "Load Time" linkage.
Next, we are going to make the C/C++ source file: DLLClient1. Select New from the File menu, then select "C/C++ Source File". In the File Name box, give it a fitting name, say, DLLClient1, then press the Enter key.
Copy and paste the following code excerpt:
<shape id="preimg2" style="WIDTH: 6.75pt; HEIGHT: 6.75pt" alt="" type="#_x0000_t75" o:spid="_x0000_i1027"><imagedata o:href="http://www.codeproject.com/images/minus.gif" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.gif"></imagedata></shape>Collapse
/***********************************************************
File name: DLLClient1.cpp
***********************************************************/
#include <iostream>
#include <conio.h>
#include <windows.h>
#include "DLLCode.h"
#pragma comment(lib,"W32DLL.lib")
using namespace std;
int main()
{
int a, b, c;
DLLclass classFromDLL;
classFromDLL.Arg = 6;
a = classFromDLL.Add(3, 2);
b = classFromDLL.Sub(3, 2);
c = classFromDLL.Arg;
cout << "DLL class Add function return: " << a << endl;
cout << "DLL class Sub function return: " << b << endl;
cout << "DLL class Arg Variable return: " << c << endl;
getch();
a = DLLArg;
b = DLLfun2(30);
DLLfun1("this is the string pass to function DLLfun1");
cout << "\n\nDLL Variable DLLArg return: " << a << endl;
cout << "DLL function DLLfun2 return: " << b << endl;
getch();
return 0;
}
Save and close this C++ source file, then minimize the VC++ Studio window. We must get some common files from the W32DLL project. So, Copy, don't move, the following files to the DLLClient1 project directory:
If you don't see the .DLL file in the Debug or Release folders, then select the View, or Tool (depending on the operating system) menu option, then select Folder Options. Next click on the View tab. Select option: Show all files. Then re-examine the Debug or Release folder.
Now maximize the VC++ Studio window, then click the "!" button to compile, build, and run the application.
If you have a DLL you use in many projects, then you can take advantage of the VC++ file architecture. Copy the DLL file into the system directory and the LIB file into the Visual C++ Lib directory. See Options on the Tools menu, and select the Directories tab, there are search directories for EXEs, SOURCE CODEs, and LIBs.
In this part, the DLL is loaded at application startup time. The Operating System searches the DLL in the following locations:
For simplicity, we just copy the common files to the target directory, DLLClient1.
Part Three, DLL Client Application Two
This DLL Client is for DLLs which do not have an export library, hints, we can't import the DLL header file. Note, we are restricted to function calls.
Now, we are going to make a Win32 console application, project DLLClient2.
In this application, the DLL is loaded during execution of the application, "Run Time" DLL linkage.
Next, we are going to make the C/C++ source file DLLClient2.
Select New from the File menu, then select "C/C++ Source File". In the File Name box, give it a fitting name, say, DLLClient2, then press the Enter key.
Copy and paste the following code excerpt:
<shape id="preimg3" style="WIDTH: 6.75pt; HEIGHT: 6.75pt" alt="" type="#_x0000_t75" o:spid="_x0000_i1025"><imagedata o:href="http://www.codeproject.com/images/minus.gif" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.gif"></imagedata></shape>Collapse
/************************************************************
File name: DLLClient2.cpp
************************************************************/
#include <conio.h> // Header file containing getch() prototype
#include <iostream>
#include <windows.h>
using namespace std;
typedef void (*MYFUN1)(char*); // pointer to: void function(char*)
typedef int (*MYFUN2)(int); // pointer to: int function(int)
int main()
{
MYFUN1 pfun1;
MYFUN2 pfun2;
HMODULE hMod; // handle to loaded library module
BOOL bRes; <span lan