<Previous Lesson

Visual Programming

Next Lesson>

Lesson#25

Threads and DLLs

25.1 IMPORT LIBRARIES ( .LIB) 2
25.2 CALLING CONVENTIONS 2
25.3 VARIABLE SCOPE IN DLL 2
25.4 RESOURCE ONLY DLL 5
25.5 DLL VERSIONS 5
25.6 GET FILE VERSION INFO 5
25.7 THREADS 6
25.7.1 THREADS AND MESSAGE QUEUING 6
25.7.2 CREATING SECONDARY THREAD 7
25.7.3 THREAD ADVANTAGES 7
25.7.4 THREAD DISADVANTAGES 7
SUMMARY 8
EXERCISES 8
Threads and DLLs 2

25.1 Import Libraries ( .lib)

Import is statically linked to Executable module.
Example of Import libraries in windows are:
Kernel32.lib
User32.lib
Gdi32.lib
Important System DLLs are
Kernel32.dll
User32.dll
Gdi32.dll

25.2 Calling Conventions

Functions used in DLL’s are normally use __stdcall calling convention. __stdcall calling
convention is a standard calling convention used by the APIs in Windows. This calling
convention cleans the stack after returning the called procedure automatically. No extra
code is needed to clean out stack. __stdcall calling convention pushes the arguments in
stack from right to left order.

25.3 Variable Scope in DLL

Variables defined in DLL have scope in memory until the DLL is loaded. After
unloading, the variable scope is vanished. Locally defined variables are accessed within
the DLL only. The variables that are set to export variables can be accessed outside the
DLL if the DLL is statically linked.
Variables can be shared across multiple processes by making the separate data section as
following.
#pragma data_seg( [ [ { push | pop }, ] [ identifier, ] ] [ "segmentname"
[, "
segment-class" ] )Specifies the data segment where initialized variables are stored in the .obj file. OBJ files
can be viewed with the dumpbin application. The default segment in the .obj file for
initialized variables is .data. Variables initialized to zero are considered uninitialized and
are stored in .bss.
Threads and DLLs
3
data_seg with no parameters resets the segment to .data.
push (optional)
Puts a record on the internal compiler stack. A push can have an identifier and
segment-name.
pop (optional)
Removes a record from the top of the internal compiler stack.
identifier (optional)
When used with push, assigns a name to the record on the internal compiler stack.
When used with pop, pops records off the internal stack until identifier is
removed; if identifier is not found on the internal stack, nothing is popped.
identifier enables multiple records to be popped with a single pop command.
"segment-name" (optional)
The name of a segment. When used with pop, the stack is popped and segmentname
becomes the active segment name.
Example
// pragma_directive_data_seg.cpp
int h = 1; // stored in .data
int i = 0; // stored in .bss
#pragma data_seg(".my_data1")
int j = 1; // stored in "my_data1"
#pragma data_seg(push, stack1, ".my_data2")
int l = 2; // stored in "my_data2"
#pragma data_seg(pop, stack1) // pop stack1 off the stack
int m = 3; // stored in "stack_data1"
int main() {
}
Data allocated using data_seg does not retain any information about its location.
#pragma comment(linker, “/SECTION: seg_data1, RWS”)
/SECTION:name,[E][R][W][S][D][K][L][P][X][,ALIGN=#]
The /SECTION option changes the attributes of a section, overriding the attributes set
when the .obj file for the section was compiled.
A section in a portable executable (PE) file is roughly equivalent to a segment or the
resources in a new executable (NE) file. Sections contain either code or data. Unlike
segments, sections are blocks of contiguous memory with no size constraints. Some
sections contain code or data that your program declared and uses directly, while other
data sections are created for you by the linker and manager (lib.exe) and contain
information vital to the operating system.
Threads and DLLs 4
Do not use the following names, as they will conflict with standard names. For example,
.sdata is used on RISC platforms:
.arch
.bss
.data
.edata
.idata
.pdata
.rdata
.reloc
.rsrc
.sbss
.sdata
.srdata
.text
.xdata
Specify one or more attributes for the section. The attribute characters, listed below, are
not case sensitive. You must specify all attributes that you want the section to have; an
omitted attribute character causes that attribute bit to be turned off. If you do not specify
R, W, or E, the existing read, write, or executable status remains unchanged.
The meanings of the attribute characters are shown below.

Character Attribute Meaning

E Execute The section is executable
R Read Allows read operations on data
W Write Allows write operations on data
S Shared Shares the section among all processes that load the
image
D Discardable Marks the section as discardable
K Cacheable Marks the section as not cacheable
L Preload VxD only; marks the section as preload
P Pageable Marks the section as not pageable
X Memory-resident VxD only; marks the section as memory-resident
K and P are peculiar in that the section flags that correspond to them are in the negative
sense. If you specify one of them on the .text section (/SECTION:.text,K), there will be
no difference in the section flags when you run DUMPBIN with the /HEADERS option;
it was already implicitly cached. To remove the default, specify /SECTION:.text,!K and
DUMPBIN will reveal section characteristics, including "Not Cached."
A section in the PE file that does not have E, R, or W set is probably invalid.
Threads and DLLs 5

To set this linker option in the Visual Studio development environment

1. Open the project's Property Pages dialog box.
2. Click the Linker folder.
3. Click the Command Line property page.
4. Type the option into the Additional Options box.

25.4 Resource Only DLL

Resource Only DLL contains only resource of different language and local types.
Resource only DLLs do not contain Entry Point or any DllMain Function.
Use of resource-only DLL is for internationalization.

25.5 DLL Versions

Version information makes it easier for applications to install files properly and enables
setup programs to analyze files currently installed. The version-information resource
contains the file's version number, intended operating system, and original file name.
You can use the version information functions to determine where a file should be
installed and identify conflicts with currently installed files. These functions enable you
to avoid the following problems:
installing older versions of components over newer versions
changing the language in a mixed-language system without notification
installing multiple copies of a in different directories
copying files to network directories shared by multiple users
The version information functions enable applications to query a version resource for file
information and present the information in a clear format. This information includes the
file's purpose, author, version number, and so on.
You can add version information to any files that can have Microsoft® Windows®
resources, such as dynamic-link libraries (DLLs), executable files, or font files. To add
the information, create a VERSIONINFO Resource and use the resource compiler to
compile the resource.

25.6 Get File Version Info

The GetFileVersionInfo function retrieves version information for the specified file.
BOOL GetFileVersionInfo(
Threads and DLLs 6
LPTSTR lptstrFilename, //file name whose version is
to get*/
DWORD dwHandle, /*unused*/
DWORD dwLen, /*length of the given buffer*/
LPVOID lpData /* buffer*/
);
lptstrFilename: Pointer to a null-terminated string that specifies the name of the file of
interest. If a full path is not specified, the function uses the search sequence specified by
the Load function.
dwHandle: This parameter is ignored.
dwLen: Specifies the size, in bytes, of the buffer pointed to by the lpData parameter.
Call the GetFileVersionInfoSize function first to determine the size, in bytes, of a
file's version information. The dwLen member should be equal to or greater than
that value.
If the buffer pointed to by lpData is not large enough, the function truncates the
file's version information to the size of the buffer.
lpData: Pointer to a buffer that receives the file-version information.
You can use this value in a subsequent call to the VerQueryValue function to
retrieve data from the buffer.
Return Value:
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information,
call GetLastError.
Call the GetFileVersionInfoSize function before calling the GetFileVersionInfo function. To retrieve information from the file-version information buffer, use the

VerQueryValue function.

25.7 Threads
25.7.1 Threads and Message Queuing

Message Queue is created when every any GDI function call is made or sendmessage or
post message function calls are made. Message Queue can be attached to every thread
either it is User interface thread or worker threads.
User Interface threads always a message queue.
Threads and DLLs 7
Worker threads are initially without message queue.
User Interface threads are those threads which are attached any GUI component such as
window.
When a process start at least one thread is running that first thread is called primary
thread other threads can made, these threads will, then, be called secondary threads.

25.7.2 Creating Secondary Thread

For creating thread we can use following functions:
_beginthread() and _endthread()
This function is a ‘C’ runtime concept from UNIX system
These functions no longer have place in Win32 systems.

The CreateThread API

In windows systems CreateThread API is used to create a thread in a process. Every
thread has its own thread procedure.
Threads can be stopped and exited using ExitThread API call.
Thread enters into running state after creating it. For thread not to be run
automatically gives the CREATE_SUSPENDED flag in CreateThread API.
Threads can be suspended or resumes after their creations by:
SuspendThread and ResumeThread.

25.7.3 Thread Advantages

Using threads has the following advantages:
1. Threads can be used to start another activity parallel. E.g. saving file on disk,
automatically while you are typing.
2. Perform different calculations parallel.

25.7.4 Thread Disadvantages

Threads major disadvantage is that they make the system slow because thread uses the
time sharing concept that is another name multitasking. A multitasking operating system
divides the available processor time among the processes or threads that need it. The
system is designed for preemptive multitasking; it allocates a processor time slice to each
thread it executes. The currently executing thread is suspended when its time slice
Threads and DLLs 8
elapses, allowing another thread to run. When the system switches from one thread to
another, it saves the context of the preempted thread and restores the saved context of the
next thread in the queue.
The length of the time slice depends on the operating system and the processor. Because
each time slice is small (approximately 20 milliseconds), multiple threads appear to be
executing at the same time. This is actually the case on multiprocessor systems, where the
executable threads are distributed among the available processors.
Note: You must use caution when using multiple threads in an application, because
system performance can decrease if there are too many threads.

Summary

Multitasking Operating systems are useful to run applications simultaneously.
Threads and processes are the key features of Operating systems. In this lecture we
studied about variable sharing in DLLs, variable scope in DLLs, DLL Versioning,
Resource only DLLs, Threads and their advantages and disadvantages. Many Threads
can work better than using single thread sometime.

Exercises

1. Create a dynamic link and make a function which displays only message
box. Export the functions using __dllexport.
2. Call the function from above in your executable module. The linking must

be static linking and use __dllimport.

<Previous Lesson

Visual Programming

Next Lesson>

Home

Lesson Plan

Topics

Go to Top

Next Lesson
Previous Lesson
Lesson Plan
Topics
Home
Go to Top