Вы находитесь на странице: 1из 22

Dynamic Link Library (DLL)

Ajay Singh
SE Trainee : C++

Nagarro Software Pvt. Ltd.

Index
Linking & Loading. Static Vs. Dynamic Libraries. DLLs in VC++.

DLL entry point, DllMain().


Exporting functions from DLL. Using exported functions from Implicit / Explicit DLL. Exporting a DLL class @ Load Time @ Run Time
Using Vtable. Using __declspec (dllexport)

Problems with Dynamic DLL

Linking and Loading


Linking
Combining set of programs, including library routines, to create loadable image. Resolving symbols defined and binding names to addresses. Generating re-locatable object code (ELF: Addresses relative to 0).

Loading
Combining multiple object files and

library modules into a single reloadable executable file. (i.e. Addresses are relative to 0) Mapping addresses within file to physical memory addresses. Resolving names of dynamic library items.

Static vs. Dynamic Linking


If several processes call the same object module of a

shared library simultaneously,


Dynamic: Only one copy in memory. Static: Several copies each for a process in memory.

Which one is better, static or dynamic? Construct some programs of different size linked in both versions to compare:
Executable Size Loading Time Running Time Number of System Calls Memory Usage

Executable Size (Byte)


Static Dynamic (Loading) Dynamic (Running)

Small Median Large Static


8000
Exe Size (Bytes)

422596 431413 443384

5152 5152 5134 Loading Time


14000
Loading Time (us)

6300 6297 6312 Running Time


30

6000 4000 2000 0 0% 30% 60% 90% 100% Percentage of Static Libraries

12000 10000 8000 6000 4000 2000 0 0% 30% 60% 90% 100% Percentage of Static Libraries

Running Time (s)

25 20 15 10 5 0 0% 30% 60% 90% 100% Percentage of Static Libraries

Loading Time
16000 14000 12000 10000 8000 6000 4000 2000 0 Small Median Large

Running Time
60 50 40
Static Loading 30 Running 20

Static Loading Running

10 0 Small Median Large

Number of

System Calls
200

Memory Usage
(Byte)

8000

150 Static Loading Running

6000

100

4000

Static Dynamic

50

2000

0 Small Median Large

One Process Five Diff Programs

Five Instances

Static linking VS. Dynamic linking


Dynamic produces smaller executable files.
Dynamic consumes less memory.

But Dynamic runs more slowly. Dynamic has more system calls.
Dynamic need more loading time.

DLLs in VC++

Dynamic-link library (DLL), is Microsoft's implementation of the Shared Library concept in the MS Windows and OS/2 Operating Systems. These libraries usually have file extension as DLL, OCX (for libraries containing ActiveX controls), or DRV (for legacy System Drivers). The file formats for DLL is, Portable Executable (PE). DLLs can contain Code, Data and Resources, in any combination.

Advantages of using DLLs: Saves memory and reduces swapping. Upgrades to the DLL are easier. Provides after-market support.. Supports multi-language programs. Provides a mechanism to extend the MFC library classes. Eases the creation of international versions (by using Resource DLLs).

DLL entry point DllMain()


DllMain(), An optional entry point into a dynamic-link library (DLL). When the system starts or terminates a process or thread, it calls the entry-point function for each loaded DLL using the first thread of the process. The system also calls the entry-point function for a DLL when it is loaded or unloaded using the LoadLibrary and FreeLibrary functions. BOOL APIENTRY DllMain( HMODULE hModule, // Base address of the DLL == HINSTANCE of a DLL. DWORD ul_reason_for_call, // why the DLL entry-point function is being called LPVOID lpReserved // Reserved by the System. ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // DLL being loaded into virtual address space. case DLL_THREAD_ATTACH: // The current process is creating a new thread. case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; // Must return TRUE, else process terminates with an error. }

TestDll.h #ifdef __cpluscplus // Automatically defined when C+ compiler is used. #define EXPORT extern "C" __declspec (dllexport) #else #define EXPORT __declspec (dllexport) #endif EXPORT void DllFunction ((LPCWSTR lpMsgText);

Exporting a function from DLL

TestDll.cpp
EXPORT void DllFunction (LPCWSTR lpMsgText) { MessageBox (GetActiveWindow (), lpMsgText, _T("DllFunction"), MB_OK); }

extern C : makes a function-name in C++ have 'C' linkage (compiler does not mangle the name) so that client code can link to/use function using a 'C' compatible header file. extern "C" forces a function to have external linkage (cannot make it static). __declspec (dllexport) : allow the compiler to generate the exported names automatically and place them in a .lib file. This .lib file can then be used just like a static .lib to link with a DLL.

DLL @ Load Time


Include header file containing declarations of all exported

functions in DLL.
#include "..\\TestDll\\TestDll.h" #pragma comment (lib, "..\\Debug\\TestDll.lib")

TestDll.lib file can now be used just like a static .lib to link functions in DLL.
Calling DLL Function:
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: DllFunction (_T(Creating Your Window)); break;

DLL @ Run Time


LoadLibrary() : Loads the specified module into the address space of the calling process. The specified module may cause other modules to be loaded. FreeLibrary() : Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. When the reference count reaches zero, the module is unloaded from the address space of the calling process and the handle is no longer valid. Example:

typedef void (CALLBACK* pFnSHOWMSG) (LPCWSTR); pFnSHOWMSG pfnShowMsg;

Case WM_CREATE:
if ((hLibrary = LoadLibrary (_T(TestDll.DLL"))) == NULL) { MessageBox (hWnd, _T(TestDll.DLL can't be loaded."), 0, MB_ICONERROR); return -1L; } // else load functions from DLL. pfnShowMsg = (pFxnSHOWMSG) GetProcAddress (hLibrary, DllFunction); pfnShowMsg (_T(Its a run-time DLL.)); FreeLibrary (hLibrary);

TestDll.h

Exporting a DLL Class

@ Load Time

#define DllExport __declspec (dllexport) class DllExport A { int m_nNum; public: A() : m_nNum (0) {} A(int n) : m_nNum (n) {} ~A() {} void SetNum (int n); int GetNum (void); };

YourApp.h
Include .h and .lib in a normal fashion
#include "..\\TestDll\\TestDll.h" #pragma comment (lib, "..\\Debug\\TestDll.lib") We can also locate TestDll.lib in Project Property.

YourApp.cpp
With DLL loaded at load time, use DLL class same way as youve defined the class in your application.

Eg.
A aObj; aObj.SetNum (2258); iClassData = aObj.GetNum ();

TestDll.cpp
void A::SetNum (int n) { m_nNum = n; } int A::GetNum (void) { return m_nNum; }

Exporting a DLL Class


TestDll.h

@ Run Time
Approach

#1

#define DllExport extern "C" __declspec (dllexport) class CSample { int m_nNum; public: CSample() : m_nNum(0) {} CSample(int n) : m_nNum(n) {} virtual ~CSample() {} // All exportable functions are declared to be virtual virtual void SetNum (int n); virtual int GetNum (void); virtual void OverloadedFx(void); virtual void OverloadedFx (int); static int m_siData; int m_iData; static int GetStaticData(); // { return m_siData; }// fx is inlined. }; // Now export methods to return CSample objects extern "C" __declspec (dllexport) CSample* CreateSampleObject_v (void); extern "C" __declspec (dllexport) CSample* CreateSampleObject_i (int n);

Exporting a DLL Class (2)


TestDll.cpp
// Functions to export Dll Class objects extern "C" __declspec (dllexport) CSample* CreateSampleObject_v (void) { return new CSample(); } extern "C" __declspec (dllexport) CSample* CreateSampleObject_i (int n) { return new CSample(n); } // Definition for CSample class member functions void CSample::SetNum (int n) {m_nNum = n; } int CSample::GetNum () { return m_nNum; } void CSample::OverloadedFx (void) { MessageBox (GetActiveWindow(), _T("Overloaded Function in Dynamic DLL\n----------\n CSample::OverloadedFx (void)"),_T("OverloadedFx (void)"), MB_ICONINFORMATION); } void CSample::OverloadedFx (int) { MessageBox (GetActiveWindow(), _T("Overloaded Function is Dynamic DLL\n-----------\n CSample::OverloadedFx (int)"),_T("OverloadedFx (int)"), MB_ICONINFORMATION); } // Definition for CSample static Data int CSample::m_siData = 1234; int CSample::GetStaticData () { return m_siData; }

Exporting a DLL Class (3)


YourApp.cpp
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HINSTANCE hLibrary; // pFx : Default CSample Constructor typedef CSample* (*pFnGET_DEF_OBJ) (void); pFnGET_DEF_OBJ pfnGetDefObj; // pFx : Parameterized CSample Constructor typedef CSample* (* pFnGETOBJ) (int); pFnGETOBJ pfnGetObj; // Pointers to TestDll Class Objects CSample* p_vObj; int iClassData; switch (message) { case WM_CREATE: hLibrary = LoadLibrary (_T(TestDll.DLL)); pfnGetDefObj = (pFnGET_DEF_OBJ) GetProcAddress (hLibrary, CreateSampleObject_v ); Contd

Exporting a DLL Class (4)


p_vObj = (pfnGetDefObj )(); // Now all the virtual functions in CSample class are accessible using vptr / vtable. iClassData = p_vObj->GetNum(); p_vObj->SetNum (2258); // Can use overloaded functions in normal obvious way. (*p_vObj).OverloadedFx (); p_vObj->OverloadedFx (1837); FreeLibrary (hLibrary); break; case // Other messages } // end of switch return DefWindowProc (hWnd, message, wParam, lParam); }
*. Exporting a DLL class using virtual functions creates a basis for COM

(Component Object Model, enable software components to communicate).

Exporting a DLL Class


TestDll.h
#define DllExport __declspec (dllexport) class DllExport A { int m_nNum; public: A() : m_nNum (0) {} A(int n) : m_nNum (n) {} ~A() {} void SetNum (int n); int GetNum (void); };

@ Run Time
Approach #2

TestDll.DEF

LIBRARY TestDll EXPORTS ConstructAi= ??0A@@QAE@H@ZPRIVATE ConstructAv= ??0A@@QAE@XZPRIVATE DestructA= ??1A@@QAE@XZPRIVATE GetNum= ?GetNum@A@@QAEHXZPRIVATE SetNum= ?SetNum@A@@QAEXH@ZPRIVATE

TestDll.cpp
void A :: SetNum (int n) { m_nNum = n; } Int A :: GetNum () { return m_nNum; }

Module DEFinition File provide the linker with information about exports, attributes, and other information about the program to be linked. Dependency Walker is a free utility that scans any 32-bit or 64-bit Windows module (exe, dll, ocx, sys, etc.) and builds a hierarchical tree diagram of all dependent modules. For each module found, it lists all the functions that are exported by that module.

YourApp.cpp

Exporting a DLL Class (2)

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HINSTANCE hLibrary; A* pDllClassObj; // Creating pointer to a member function type typedef void (A::*pFnConstructorOfAi) (int); typedef void (A::*pFnConstructorOfAv) ();// i : int, v : void typedef void (A::*pFnSetNumOfA) (int); typedef int (A::*pFnGetNumOfA) (void); switch (message) { case WM_CREATE: hLibrary = LoadLibrary (_T(TestDll.DLL)); pDllClassObj = (A*) _alloca (sizeof(A)); pFnConstructorOfAv pfnConsDefA = reinterpret_cast <pFnConstructorOfAv> (GetProcAddress (hTestLibrary, " ConstructAv")); pFnSetNumOfA pfnSetNum = reinterpret_cast < pFnSetNumOfA > (GetProcAddress (hTestLibrary, " SetNum")); pDllClassObj->pfnSetNum (2258); // and same way use rest of the class functions

Exporting a DLL Class


Problems with: Overloaded Functions

@ Run Time

Suppose were loading DLL at run-time and have done something like: #define DllExport __declspec (dllexport) class DllExport DLLClass { }; We cant export overloaded functions with single name, since .DEF file must contain unique entries for C++ mangled (decorated) class member functions.
Static Data Member
o A static declared variable seems not to be consistent over DLL boundaries.
o The static member is not accessed directly by code in the calling application, only

through member functions of the class in the dll. o inline functions accessing the static member: Those functions will be inline expanded into the calling applications code making the calling application access the static member directly. That will violate the finding referenced above that static variables are local to the dll and cannot be referenced from the calling application.

Thank You!

Вам также может понравиться