Windows NT Systems Programming: Spring 1999

[ Home | Syllabus | Course Notes | Assignments | Search]


Dynamic Linked Libraries


Why DLLs


Separate Compilation

dll.gif (8239 bytes)


Simple Example: Library Side

Exported Function (snd.cpp)

// snd.cpp

#include <windows.h>

#include "snd.h" 
void MultiHonk(DWORD iterations)
{
  UINT i;

  for (i=0; i<iterations; i++)
  {
    Beep(200, 50);
    Sleep(1000);
  }
}
rainbow.gif (2243 bytes)
// Header file for library side
// snd.h

extern "C"
{
  void MultiHonk(DWORD iterations); // plain old function prototype
}
rainbow.gif (2243 bytes)

The Glue (snd.def)

; snd.def

LIBRARY snd

EXPORTS
	MultiHonk

 

rainbow.gif (2243 bytes)
// Used by "lib" command e.g.
lib -def:snd.def -machine:i386 -out:snd.lib

Application Code

// honker1.cpp
// No evidence of using a DLL
#include <windows.h>
#include <stdlib.h>
#include <iostream.h>

#include "sndlt.h" // same as snd.h above

VOID main(VOID)
{
  DWORD iterations;
  CHAR iterStr[100];

  cout << "Enter the number of beeps to produce: ";
  cin.getline(iterStr, 100);

  iterations=atoi(iterStr);

  // make the beeps
  MultiHonk(iterations);
}

Using DLLs

Normally, they are created and stored in known directories.

 

APP=honker1
NODEBUG=1

!include <ntwin32.mak>

$(APP).exe: $(APP).obj
	$(link) $(conlflags) $(ldebug) \
	  $(conlibs) snd.lib $(APP).obj \
	  -out:$(APP).exe

$(APP).obj: $(APP).cpp sndlt.h
	$(cc) $(cflags) $(cdebug) $(cvars) \
	  $(APP).cpp

RunTime vs LoadTime Linking

The above example was made easier by using Load Time Linking.

RUN TIME LINKING:

E.G. Loading the MAPI.DLL e-mail functions in WORD


Application using RunTime Linking

 

// sndrt.h

void (*MultiHonk)(DWORD iterations);
rainbow.gif (2243 bytes)
// honker2.cpp

#include <windows.h>
#include <stdlib.h>
#include <iostream.h>

#include "sndrt.h"

VOID main(VOID)
{
  DWORD iterations;
  CHAR iterStr[100];
  CHAR modName[MAX_PATH];
  HINSTANCE sndHandle;

  cout << "Enter the number of beeps to produce: ";
  cin.getline(iterStr, 100);

  iterations=atoi(iterStr);

  // map snd.dll into process
  sndHandle=LoadLibraryEx("snd", NULL, 0);

  if (sndHandle == NULL)
  {
    cerr << "Sorry, unable to use DLL." << endl;
    return;
  }
  else
  {
    // load function name with address mapped from
    // snd.dll
    MultiHonk=(void (*)(DWORD))GetProcAddress(
      sndHandle, "MultiHonk");

    if (MultiHonk == NULL)
    {
      cerr 
        << "Sorry, MultiHonk function not in DLL."
        << endl;
      // release the DLL
      FreeLibrary(sndHandle);
      return;
    }
    else
    {
      GetModuleFileName(sndHandle, modName,
        MAX_PATH);
      cout << "Using DLL: " << modName
        << endl;

      // make the beeps
      MultiHonk(iterations);
      // release the DLL
      FreeLibrary(sndHandle);
    }
  }
}
rainbow.gif (2243 bytes)

DLL Entry Points


Simple Demonstration

// snd.cpp

#include <windows.h>

#include "snd.h"

BOOL WINAPI SndEntryPoint(HINSTANCE dllHandle,
  DWORD reason, LPVOID situation)
{
  CHAR buf[80];

  switch(reason)
  {
    case DLL_PROCESS_ATTACH:
      if (situation)
        wsprintf(buf, "DLL statically loaded.");hptrd_left.gif (955 bytes)
      else
        wsprintf(buf, "DLL dynamically loaded.");
      break;

    case DLL_THREAD_ATTACH:
      wsprintf(buf, "New thread starting.");
      break;

    case DLL_PROCESS_DETACH:
      if (situation)
        wsprintf(buf, "DLL released by system.");
      else
        wsprintf(buf, "DLL released by program.");
      break;

    case DLL_THREAD_DETACH:
      wsprintf(buf, "Thread terminating.");
      break;

    default:
      return FALSE;
  }

  MessageBox(NULL, buf, "DLL Info",
    MB_OK | MB_ICONINFORMATION);
  return TRUE;
}

void MultiHonk(DWORD iterations)
{
  UINT i;

  for (i=0; i<iterations; i++)
  {
    Beep(200, 50);
    Sleep(1000);
  }
}
rainbow.gif (2243 bytes)

Memory Models for DLLs


Example of ADT "stack" DLL

 

// stack.h

typedef struct _stacknode
{
	int data;
	struct _stacknode *next;
} stacknode, *stack;

extern "C"
{
	void init(stack *s);
	void push(stack *s, int i);
	int pop (stack *s);
	void destroy(stack *s);
}

 

rainbow.gif (2243 bytes)
// stack.cpp

#include <windows.h>
#include "stack.h"

void init(stack *top)
{
  *top=0;
}

void push(stack *top, int value)
{
  stacknode *temp;

  temp = (stacknode *) GlobalAlloc(GPTR, 
    sizeof stacknode);
  temp->data = value;
  temp->next = *top;
  *top = temp;
}

int pop(stack *top)
{
  stacknode *temp;
  int value;

  if (*top == 0) 
    return 0;
  temp = *top;
  value = (*top)->data;
  *top = (*top)->next;
  delete temp;
  return value;
}

void destroy(stack *top)
{
  while (*top != 0);
    pop(top);
}
rainbow.gif (2243 bytes)

Copyright chris wild 1999.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: December 28, 1998.