Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 34

Systems Programming

Dynamic Link Libraries


Outline
• DLL Libraries
• DllMain
• Linking a DLL
Dynamic-Link Libraries
• DLL is a module that contain functions and
data that can be used by another module
(application or DLL)
• It can define two kinds of functions
– Exported
• Intended to be called by other modules
– Internal
• Intended to be called only from within the DLL
Dynamic-Link Libraries
• Dynamic Link Libraries (DLL) are an important
structural component of Microsoft Windows.
• DLLs allow certain code fragments to be compiled into a
single library, and to be linked to by multiple programs.
– This means that only one copy of the library needs to exist, and
multiple programs can share the functions and the data between
them.
– The difference between a DLL and a static library is that when
you compile your programs, the DLL is not compiled into your
executable, but instead remains a separate module.
– This feature helps to keep executable size low, and also allows
for a DLL to be loaded into memory only when it is needed.
• The exact method of building a DLL file is dependant on
the compiler you are using.
– However, the way in which DLLs are programmed is universal.
We will talk about how to program DLL files later.
Advantages of Using DLL
• Some advantages over static linking
– Smaller program image
– Save system memory, since multiple
processes can share a single copy of the DLL
– Easy to support new versions or alternative
implementations
– Run time decision of which version to use
__declspec
• The __declspec keyword is a strange new
keyword that is not part of the ANSI C
standard, but that most compilers will
understand anyway.
• __declspec allows a variety of non-
standard options to be specified, that will
affect the way a program runs.
• Specifically, there are two __declspec
identifiers that we want to discuss:
__declspec(dllexport)
__declspec(dllimport)
__declspec - dllexport
• When writing a DLL, we need to use the
dllexport keyword to denote functions that
are going to be available to other
programs.
– Functions without this keyword will only be
available for use from inside the library itself.
– Here is an example:
__declspec(dllexport) int MyFunc1(int foo)
__declspec – where to use it

• The __declspec identifier for a function


needs to be specified both in the function
prototype and the function declaration,
when building a DLL.
__declspec – Importing a DLL
• To "import" a DLL function from a regular
program, we need to link to the DLL, and we
need to prototype the function with the dllimport
keyword as such:
__declspec(dllimport) int MyFunc1(int foo);
• Now the program can use the function as normal,
even though the function exists in an external
library. The compiler works with Windows to
handle all the details for you.
• If the calling (importing) client program is written
in C++, it is necessary to specify the C calling
convention
– extern “C” _declspec(dllimport) DWORD …
__declspec - Common Macro
• Many people find it useful to define a single
header file for their DLL, instead of maintaining
one header file for building a DLL, and one
header file for importing a DLL.
• Here is a macro that is common in DLL creation:
#ifdef BUILDING_DLL
#define DLL_FUNCTION __declspec(dllexport)
#else
#define DLL_FUNCTION __declspec(dllimport)
#endif
__declspec - Common Macro
• Now, to build the DLL, we need to define the
BUILDING_DLL macro, and when we are importing the
DLL, we don't need to use that macro.
• Functions then can be prototyped as such:
• DLL_FUNCTION int MyFunc1(void);
• DLL_FUNCTION int MyFunc2(void); ...

• NOTE: Microsoft did not intend for this __declspec


syntax to be used. Instead the intention was that the
public api of a DLL would be declared in an "exports" file.
However the above syntax, despite requiring the macro
to switch it back and forth, was much more convenient
and is pretty much used by all software today.
DllMain
• When Windows links a DLL to a program,
Windows calls the library's DllMain function.
• This means that every DLL needs to have a
DllMain function.
• The DllMain function needs to be defined as
such:
BOOL APIENTRY DllMain (HINSTANCE hInstance,
DWORD reason, LPVOID reserved)
DllMain
• DllMain is 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.
• Warning:
– There are serious limits on what you can do in a DLL
entry point. To provide more complex initialization,
create an initialization routine for the DLL. You can
require applications to call the initialization routine
before calling any other routines in the DLL.
General template for a DllMain function
BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}

• However, if you aren't interested in any of the reasons, you can


remove the entire switch statement from your program and return
TRUE.
DllMain
• The DllMain function doesn't need to do
anything special for these cases, although some
libraries will find it useful to allocate storage for
each new thread or process that is being used
with the library.
• The DllMain function must return TRUE if the
library loaded successfully, or FALSE if the
library had an error and could not load. If you
return FALSE, the program will pop up a warning
message and crash.
DllMain
• The keywords "BOOL", "APIENTRY", "HINSTANCE",
etc., are all defined in <windows.h>. So, you must include
that file even if you don't use any Win32 API functions in
your library.
• APIENTRY is just a keyword that Windows uses
internally. So, you don't need to worry about it.
• The variable "hInstance" is the HINSTANCE handle for
the library, and you can keep this and use it, or you can
trash it. reason will be one of four different values:
– DLL_PROCESS_ATTACH
• a new program has just linked to the library for the first time.
– DLL_PROCESS_DETACH
• a program has unlinked the library.
– DLL_THREAD_ATTACH
• a thread from a program has linked to the library.
– DLL_THREAD_DETACH
• a thread from a program has just unlinked the library.
Dynamic-Link Libraries - Linking
Methods
• 2 types of dynamic linking
– Load-time linking (Implicit/static)
• Required to link the module with the import library
(.lib and .dll files)
• Easier to use
– Run-time linking (Explicit/dynamic)
• Use LoadLibrary or LoadLibraryEx to load the
DLL at run time
• Use GetProcAddress function to get the
addresses for the exported DLL functions
• FreeLibrary – unloads the DLL
Load-time linking (Implicit)
• Implicit linking occurs when an
application's code calls an exported DLL
function.
• When the source code for the calling
executable is compiled or assembled, the
DLL function call generates an external
function reference in the object code.
• To resolve this external reference, the
application must link with the import library
(.lib file) provided by the maker of the DLL.
Load-time linking (Implicit)
• The import library only contains code to load the
DLL and to implement calls to functions in the
DLL.
• Finding an external function in an import library
informs the linker that the code for that function
is in a DLL.
• To resolve external references to DLLs, the
linker simply adds information to the executable
file that tells the system where to find the DLL
code when the process starts up.
Load-time linking (Implicit)
• When the system starts a program that
contains dynamically linked references, it
uses the information in the program's
executable file to locate the required DLLs.
• If it cannot locate the DLL, the system
terminates the process and displays a
dialog box that reports the error.
• Otherwise, the system maps the DLL
modules into the process's address space.
Load-time linking (Implicit)
• If any of the DLLs has an entry-point function
(for initialization and termination code), the
operating system calls the function.
• One of the parameters passed to the entry-point
function specifies a code that indicates the DLL
is attaching to the process.
• If the entry-point function does not return TRUE,
the system terminates the process and reports
the error.
• Finally, the system modifies the executable code
of the process to provide starting addresses for
the DLL functions.
Load-Time Function Interface in DLL
• When the system starts a program, it uses
the information the linker placed in the file
to locate the names of DLLs
– Search orders (typical)
• The directory from which the application loaded
• The system directory
• The 16-bit system directory
• The windows directory
• The current directory
• The directories that are listed in the PATH
How to Link Implicitly
• To implicitly link to a DLL, executables must
obtain the following from the provider of the DLL:
– A header file (.h file) containing the declarations of the
exported functions and/or C++ classes. The classes,
functions, and data should all have
__declspec(dllimport)
– An import library (.LIB files) to link with. (The linker
creates the import library when the DLL is built.)
– The actual DLL (.dll file).
How to Link Implicitly
• Executables using the DLL must include the header file
containing the exported functions (or C++ classes) in
each source file that contains calls to the exported
functions.
• From a coding perspective, the function calls to the
exported functions are just like any other function call.
• To build the calling executable file, you must link with the
import library. If you are using an external makefile,
specify the file name of the import library where you list
other object (.obj) files or libraries that you are linking
with.
• The operating system must be able to locate the DLL file
when it loads the calling executable.
Recap
• Use _declspec(dllexport) to declare a function to be
exportable
– _declspec(dllexport) DWORD MyFunction(…);
• The build process will create .DLL and .LIB files
– You should Link the .LIB file with the calling program
– The .LIB file acts like a mini static library, that tells the linker to
statically link the associated DLL file.
– When using a DLL in a project, you can either provide the linker
with the .LIB stub file, or some linkers allow you to specify the
DLL directly (and the linker will then try to find the .LIB file, or may
even attempt to create the .LIB file automatically).
• Similar syntax to import a function
– _declspec(dllimport) DWORD MyFunction(…);
• If the calling (importing) client program is written in C++,
necessary to specify the C calling convention
– extern “C” _declspec(dllimport) DWORD …
Run-time Linking (Explicit)
• Requires the program to request
specifically that a DLL be loaded or freed
• Then, the program obtains the address of
the required entry point and uses that
address as the pointer in the function call
• It is also known as Loading DLLs
Dynamically
Loading DLLs Dynamically
• The real power behind DLL files is that they can be
loaded into your program dynamically at execution time.
• This means that while your program is running, it can
search for and load in new components, without needing
to be recompiled.
• This is an essential mechanism for programs that allow
plug-ins and extensions to be loaded at execution time.
• To Dynamically load the DLL file, you can call the
LoadLibrary function to get a handle to that library, and
then pass that handle to one of several other functions to
retrieve data from the DLL.
LoadLibrary
• A function used for mapping the specified executable
module into the address space of the calling process
• `The prototype for LoadLibrary is:
HMODULE WINAPI LoadLibrary(LPCTSTR lpFileName); or
HINSTANCE LoadLibrary(LPCTSTR lpLibFileName);
• HMODULE (HINSTANCE) is a HANDLE to a program
module.
• lpFileName (lpLibFileName ) is the file name of the DLL
you want to load.
• Keep in mind that when loading a module, the system
will check in your PATH first.
– If you want the system to check in other specified directories
first, use the SetDllDirectory function first.
LoadLibrary
• Once a DLL is loaded, and you have a handle to
the module, you can do various things:
– Use GetProcAddress to return a function pointer to a
function in that library.
– Use LoadResource to retrieve a resource from the
DLL.
– Once you are finished with a DLL file, and you want to
remove it from memory, you can call the FreeLibrary
function with the DLL's module handle.
GetProcAddress
• A function used for retrieving the address
of an exported function or variable from
the specified DLL
• FARPROC GetProcAddress(HMODULE
hModule, LPCTSTR lpProcNameName);
Example: myPuts (Creating a .dll )
Example: Load-time Linking - Calling
Program
Example: Run-time Linking
Homework
• Writing a DLL
• Writing programs to use your DLL
– Using load time linking
– Using run time linking

You might also like