400 likes | 633 Views
Dynamic Link Libraries: Inside Out. Dynamic Link Libraries About Dynamic-Link Libraries Dynamic-Link Libraries Hands On Dynamic Link Library Reference Trouble Shooting. About Dynamic Link Libraries Advantages of Dynamic Linking Dynamic-Link Library Creation
E N D
Dynamic Link Libraries • About Dynamic-Link Libraries • Dynamic-Link Libraries Hands On • Dynamic Link Library Reference • Trouble Shooting
About Dynamic Link Libraries • Advantages of Dynamic Linking • Dynamic-Link Library Creation • Dynamic-Link Library Entry-Point Function • Load-Time Dynamic Linking • Run-Time Dynamic Linking • Dynamic-Link Library Data • Dynamic-Link Library Redirection • Dynamic-Link Library Updates
Advantages of DynamicLinking • Saves memory and reduces swapping • No recompilation • A DLL can provide after-market support • Programs written in different languages can call the same DLL functions
Advantages of Dynamic Linking __cdecl Calling Convention Default calling convention for C and C++ programs. Stack is cleaned up by the caller and hence it can do vararg functions. The __cdecl calling convention creates larger executables than __stdcall, because it requires each function call to include stack cleanup code. __stdcall Calling Convention The __stdcall calling convention is used to call Win32 API functions. • The callee cleans the stack, so the compiler makes vararg functions __cdecl • Functions that use this calling convention require a function prototype.
Dynamic Link Library Creation • Creating Source Files • Exporting Functions • Creating an Import Library Warning:Calling the ExitProcess function in a DLL can lead to unexpected application or system errors. Be sure to call ExitProcess from a DLL only if you know which applications or system components will load the DLL and that it is safe to call ExitProcess in this context.
Dynamic Link Library Entry Point The system calls the entry-point function whenever processes and threads load or unload the DLL. Calling the Entry-Point Function The system calls the entry-point function whenever any one of the following events occurs: • A process loads the DLL. • A process unloads the DLL. • A new thread is created in a process that has loaded the DLL. Use DisableThreadLibraryCalls function to disable notification when threads are created. • A thread of a process that has loaded the DLL terminates normally, not using TerminateThread or TerminateProcess.
Dynamic Link Library Entry Point ( Contd … ) Entry-Point Function Definition The DLL entry-point function must be declared with the standard-call calling convention. DLL entry point can be called in following scenarios: • A process loads the DLL (DLL_PROCESS_ATTACH) • The current process creates a new thread (DLL_THREAD_ATTACH) • A thread exits normally (DLL_THREAD_DETACH) • A process unloads the DLL (DLL_PROCESS_DETACH) Should perform only simple initialization tasks, such as setting up thread local storage (TLS), creating synchronization objects, and opening files
Dynamic Link Library Entry Point ( Contd … ) Entry-Point Function ExampleBOOL WINAPI DllMain( HINSTANCE hinstDLL, // handle to DLL module DWORD fdwReason, // reason for calling function LPVOID lpReserved ) // reserved { // Perform actions based on the reason for calling. switch( fdwReason ) { case DLL_PROCESS_ATTACH: // Initialize once for each new process. Return FALSE to fail DLL load. break; case DLL_THREAD_ATTACH: // Do thread-specific initialization. break; case DLL_THREAD_DETACH: // Do thread-specific cleanup. break; case DLL_PROCESS_DETACH: // Perform any necessary cleanup. break; } return TRUE; // Successful DLL_PROCESS_ATTACH. }
Dynamic Link Library Entry Point ( Contd … ) Entry-Point Function Return Value TRUE indicates success. FALSE indicates failure.
Load Time Dynamic Linking When the system starts a program that uses load-time dynamic linking, it uses the information in the file to locate the names of the required DLL(s). Following search sequence will be used to locate DLLs. • The directory from which the application loaded. • The current directory. • The Windows system directory. Use the GetSystemDirectory function to get the path of this directory. • The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched. The name of this directory is System. • The Windows directory. Use the GetWindowsDirectory function to get the path of this directory. • The directories that are listed in the PATH environment variable. The DLL is mapped into the virtual address space of the process during its initialization and is loaded into physical memory only when needed.
Run Time Dynamic Linking Loaded using LoadLibrary or LoadLibraryEx Standard search sequence will be used to locate DLLs. Two DLLs that have the same base file name and extension but are found in different directories are not considered to be the same DLL. The system calls the entry-point function in the context of the thread that called LoadLibrary or LoadLibraryEx. If the system cannot find the DLL or if the entry-point function returns FALSE, LoadLibrary or LoadLibraryEx returns NULL. The process can use GetProcAddress to get the address of an exported function in the DLL using a DLL module handle returned by either LoadLibrary, LoadLibraryEx, or GetModuleHandle
Run Time Dynamic Linking ( Contd … ) When the DLL module is no longer needed, the process can call FreeLibrary or FreeLibraryAndExitThread. Run-time dynamic linking enables the process to continue running even if a DLL is not available. Run-time dynamic linking can cause problems if the DLL uses the DllMain function to perform initialization for each thread of a process, because the entry-point is not called for threads that existed before LoadLibrary or LoadLibraryEx is called.
Dynamic-Link Library Data DLLs can contain global data or local data. The default scope of DLL variables is the same as that of variables declared in the application. When a DLL allocates memory using any of the memory allocation functions (GlobalAlloc, LocalAlloc, HeapAlloc, and VirtualAlloc), the memory is allocated in the virtual address space of the calling process and is accessible only to the threads of that process. The thread local storage (TLS) functions enable a DLL to allocate an index for storing and retrieving a different value for each thread of a multithreaded process Warning: VC++ compiler supports a syntax that enables you to declare thread-local variables: _declspec(thread). If you use this syntax in a DLL, you will not be able to load the DLL explicitly using LoadLibrary or LoadLibraryEx. If your DLL will be loaded explicitly, you must use the thread local storage functions instead of _declspec(thread).
Dynamic-Link Library Redirection Starting with Windows 2000, you can ensure that your application uses the correct version of a DLL by creating a redirection file. The redirection file must be named as “appname.local” Example: An application c:\myapp\myapp.exe calls LoadLibrary using the path c:\program files\common files\system\mydll.dll. If c:\myapp\myapp.exe.local and c:\myapp\mydll.dll exist, LoadLibrary will load c:\myapp\mydll.dll. Otherwise, LoadLibrary will load c:\program files\common files\system\mydll.dll.
Dynamic-Link Library Updates It is sometimes necessary to replace a DLL with a newer version It is not necessary to restart the computer if you perform the following • Use the MoveFileEx function to rename the DLL being replaced. • Copy the new DLL to the directory that contains the renamed DLL. All applications will now use the new DLL. • Use MoveFileEx with MOVEFILE_DELAY_UNTIL_REBOOT to delete the renamed DLL.
Dynamic Link Libraries Hands On • Creating A Load Time DLL • Creating A Run Time DLL • Using Load-Time Dynamic Loading • Using Run-Time Dynamic Loading • Using Shared Memory In Dynamic Link Library • Using Thread Local Storage In Dynamic Link Library Create a blank workspace named “DLLsTraining”
Creating A Load Time DLL Add a new “Win32 Dynamic-Link Library” project with name “LoadTimeDLL” to the workspace “DLLsTraining”. Choose an empty DLL project Add a new file named “LoadTimeDLL.cpp”and“LoadTimeDLL.h”to LoadTimeDLL project. Add code shown below to “LoadTimeDLL.cpp” and “LoadTimeDLL.h”
Creating A Load Time DLL ( Contd … ) LoadTimeDLL.cpp #include <windows.h> // Define the symbol LOAD_TIME_DLL_EXPORTS before including // "LoadTimeDll.h". This makes the __declspec(dllexport) visible to the // implementing .cpp file. When using this header in other modules, don’t define // this symbol. Then those modules will see __declspec(dllimport). This makes // those modules to import the function form the DLLs. #define LOAD_TIME_DLL_EXPORTS #include "LoadTimeDLL.h" void SayLoadTimeDLL() { MessageBox(NULL, TEXT(“Information"), TEXT("I am a load time DLL"),MB_OK); }
Creating A Load Time DLL ( Contd … ) LoadTimeDLL.h //Add the include guards to protect from cyclic an redundant inclusions #ifndef _LOAD_TIME_DLL_H #define _LOAD_TIME_DLL_H #ifdef LOAD_TIME_DLL_EXPORTS // This is syntax that has to be followed to export a function that can be used // from other module, which loaded this dll. “__declspec(dllexport)” tells the // compiler to export the definition of this function. extern __declspec(dllexport) void SayLoadTimeDLL() ; #else // This is syntax that has to be visible for the module that uses this function. // “__declspec(dllimport)” tells the compiler to bring the definition of this // function from a DLL. extern __declspec(dllimport) void SayLoadTimeDLL() ; #endif #endif
Creating A Load Time DLL ( Contd … ) Compile the project LoadTimeDLL. The out put would be: --------------------Configuration: LoadTimeDLL - Win32 Debug-------------------- Compiling... LoadTimeDLL.cpp Linking... Creating library Debug/LoadTimeDLL.lib and object Debug/LoadTimeDLL.exp LoadTimeDLL.dll - 0 error(s), 0 warning(s) If the generation of “LoadTimeDLL.lib” is absent, it means no functions were exported and DLL cannot be loaded used. (To test change the name of the SayLoatimeDLL to SayLoadtimeDll. Observe case.)
Creating A RunTime DLL Add a new “Win32 Dynamic-Link Library” project with name “RunTimeDLL” to the workspace “DLLsTraining”. Choose an empty DLL project Add a new file named “RunTimeDLL.cpp”, “RunTimeDLL.h”and “RunTimeDLL.def” to RunTimeDLL project. Add code shown below to “RunTimeDLL.cpp” and “RunTimeDLL.h”
Creating A RunTime DLL ( Contd … ) RunTimeDLL.cpp #include <windows.h> #include "RunTimeDLL.h" // Definition of the function which will be exported to other modules. void SayRunTimeDLL() { MessageBox( NULL, TEXT("I am a run time DLL"), TEXT(“Information"), MB_OK ); }
Creating A RunTime DLL ( Contd … ) RunTimeDLL.h // Add the include guards to protect from cyclic an redundant inclusions #ifndef _RUN_TIME_DLL_H #define _RUN_TIME_DLL_H // Here the function will be exported using .def file. So no need to export using the // declspec. This is the way to export the function from an dll that can be loaded at // runtime and asked for the addresses of the function. void SayRunTimeDLL() ; #endif
Creating A RunTime DLL ( Contd … ) RunTimeDLL.def LIBRARY "RunTimeDLL" EXPORTS SayRuntimeDLL
Creating A RunTime DLL ( Contd … ) Compile the project RunTimeDLL. The out put would be: --------------------Configuration: RunTimeDLL - Win32 Debug-------------------- Compiling... RunTimeDLL.cpp Linking... Creating library Debug/RunTimeDLL.lib and object Debug/RunTimeDLL.exp RunTimeDLL.dll - 0 error(s), 0 warning(s) If the generation of “RunTimeDLL.lib” is absent, it means no functions were exported and DLL cannot be loaded used. (To test change the name of the SayRunTimeDLL to SayRunTimeDll in .def file. Observe case.)
Using Load Time Loading Add a new “Win32 Console Application” project with name “UsingLoadTimeDLL” to the workspace “DLLsTraining”. Choose an empty project Using Project->Dependencies, add the dependence on LoadTimeDLL. Add a new file named “UsingLoadTimeDLL.cpp”. Add code shown below to “UsingLoadTimeDLL.cpp”
Using Load Time Loading ( Contd … ) UsingLoadTimeDLL.cpp // Using LoadTimeDlls functionality by imporying header file. // Don't define LOAD_TIME_DLL_EXPORTS symbol. Absence of this // symbol makes the __declspec(dllimport) visible to this file and hence // forces the compiler to fetch the definition form the DLL. #include “../LoadTimeDLL/LoadTimeDLL.h” int main() { // You can directly make a call to exported functions of the load time DLL. // Call a function of the Load time loaded DLL. SayLoadTimeDLL(); return 0 ; }
Using Load Time Loading ( Contd … ) Compile the project. Copy the LoadTimeDLL.dll to the directory in which UsingLoadTimeDLL.exe presents. Run UsingLoadTimeDLL.exe. This will pop up a message box saying “I am a load time DLL”.
Using Run Time Loading Add a new “Win32 Console Application” project with name “UsingRunTimeDLL” to the workspace “DLLsTraining”. Choose an empty project Add a new file named “UsingRunTimeDLL.cpp”. Add code shown below to “UsingRunTimeDLL.cpp”
Using Run Time Loading ( Contd … ) UsingRunTimeDLL.cpp #include <windows.h> int main() { // Load the run time DLL and ask for the address of the exported function. // It is always advised to check the return values of the calls, as it is quite // possible to get the NULL pointers as return values. HMODULE runTimeDLLHandle = LoadLibrary(TEXT("RunTimeDll.DLL")); if(runTimeDLLHandle == NULL) { MessageBox(NULL, TEXT("Failed to load the DLL"), TEXT("Error"), MB_OK ); return 0 ; }
Using Run Time Loading ( Contd … ) else { // Define a user define Function Pointer type. This type will vary from the // function to function depending on their return types and parameters list. typedef void (*MyProc)(); // Query for the address of the function “SayRuntimeLoadDLL” MyProc runtimeDLLFn = (MyProc)GetProcAddress(runTimeDLLHandle, TEXT("SayRuntimeLoadDLL")); if( NULL == runtimeDLLFn ) { MessageBox(NULL, TEXT("SayRunTimeDLL function not exposed."), TEXT("Error"), MB_OK ); return 0 ; } runtimeDLLFn (); } return 1 ; }
Using Load Time Loading ( Contd … ) Compile the project. Copy the RunTimeDLL.dll to the directory in which UsingRunTimeDLL.exe presents. Run UsingRunTimeDLL.exe. This will pop up a message box saying “I am a run time DLL”.
Dynamic Link Library Reference DisableThreadLibraryCalls: Disables thread attach and thread detach notifications for the specified DLL. DllMain An optional entry point into a DLL. FreeLibrary Decrements the reference count of the loaded DLL. When the reference count reaches zero, the module is unmapped from the address space of the calling process. FreeLibraryAndExitThread Decrements the reference count of a loaded DLL by one, and then calls ExitThread to terminate the calling thread.
Dynamic Link Library Reference ( Contd … ) GetModuleFileName Retrieves the full path and file name for the file containing the specified module. GetModuleHandle Retrieves a module handle for the specified module. GetModuleHandleEx Retrieves a module handle for the specified module. GetProcAddress Retrieves the address of an exported function or variable from the specified DLL.
Dynamic Link Library Reference ( Contd … ) LoadLibrary Maps the specified executable module into the address space of the calling process. LoadLibraryEx Maps the specified executable module into the address space of the calling process.
Trouble Shooting • Runtime loading of the DLL is failing • The DLL is not in the path that can be located by system • The entry point setting of the DLL has changed • DLL entry point function is returning FALSE • Failed to get the procedure address from DLL • The exporting of the function may not be correct. • Use .def file to export the functions.
Trouble Shooting ( Contd … ) • System Crashing while accessing global data • If your system is multi threaded, ensure that the data is protected across the threads. • How to export a class? • Exactly similar to that of function except the __declspec should come between the keyword class and the name of the class. Example: • class __declspec(dllexport) CexportedClass • The module that is using this call should see a declaration likeclass __declspec(dllimport) CexportedClass
Trouble Shooting ( Contd … ) • Weird “User breakpoint called from code at 0x77f7629c” • In project settings-->C/C++->Code Generation category choose “Multithreaded DLL” under “Use runtime library” heading.