DLL Explicit Loading

 

Introduction

 

So far, in order to use a library, whether static or DLL, we made sure we new where the library was located. In fact, we kept copying it in the directory where we created it and pasted in the directory of the application that needed it. Suppose someone else or a certain company created the library and distributed it, either with Microsoft Windows or the DLL was installed with another application. To use such a library, of course you can find it, copy it, and paste it in the project where you want to use it. If many other programs are accessing such a DLL, there would be no need to copy and paste it like that. These types of DLL are installed in the Windows directory so any program that needs them can access them from there.

As you can see, Microsoft Windows installed many DLLs in the Windows or Windows\System32 directory. You too, when creating the executable of your program, you can install the DLL there so you would know with certainty where the DLL is located.

Practical Learning: Creating an MFC Static Library

  1. To start a new application, open the New dialog box (File -> New...) and, in the Projects property page, click Win32 Dynamic-Link Libraries. In the Project Name box, type ExplicitDLL1 and press Enter
  2. In the Win32 Dynamic-Link Library Step 1 of 1, make sure the An Empty DLL Project radio button is selected.
    Click Finish then click OK
  3. To add a header file, on the main menu, click File -> New…
  4. In the New dialog box and in the Files property page, click C/C++ Header File
  5. In the Name edit box, type stdafx and press Enter
  6. In the empty file, type the following:
     
    #ifndef STDAFX_H_
    #define STDAFX_H_
    
    #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
    
    #include <windows.h>
    
    #endif // STDAFX_H_
  7. To add the accompanying source file, display the New dialog box and select C++ Source File
  8. In the Name edit box, type stdafx and press Enter
  9. In the empty file, type the following:
     
    #include "stdafx.h"
  10. To add a new source file, on the main menu, click File -> New...
  11. In the Name edit box, type exo1 and press Enter
  12. In the empty file, type the following:
     
    #include "stdafx.h"
    
    BOOL APIENTRY DllMain( HANDLE hModule, 
                                           DWORD  ul_reason_for_call, 
                                           LPVOID lpReserved )
    {
        return TRUE;
    }
  13. To add a header file, on the main menu, click File -> New…
  14. In the New dialog box and in the Files property page, click C/C++ Header File
  15. In the Name edit box, type head and press Enter
  16. In the empty file, type the following:
     
    #pragma once
    
    double GetNumber(double n);
  17. To add the accompanying source file, display the New dialog box and select C++ Source File
  18. In the Name edit box, type head and press Enter
  19. In the empty file, type the following:
     
    #include "stdafx.h"
    #include "head.h"
    
    double GetNumber(double Nbr)
    {
    	return Nbr * 4.12;
    }
  20. To add a definition file, display the New dialog box again
  21. In the Files property page, click Text File
  22. In the Name edit box, type "exo1.def" and press Enter
  23. In the empty file, type the following:
     
    LIBRARY ExplicitDLL1
    
    EXPORTS
    	GetNumber
  24. To create the DLL, on the main menu, click Build -> Build ExplicitDLL1.dll
  25. Open Windows Explorer or My Computer and locate the folder that contains the above ExplicitDLL1 project then open its Debug folder
  26. Select and copy both the ExplicitDLL1.dll and the ExplicitDLL1.lib files
  27. Paste them in your Windows\System32 folder

Explicit Loading a DLL

The technique of calling a DLL as we have proceeded so far is referred to as implicit loading because we knew how we created the DLL and we added it to the directory of the application we were creating. This allowed us to add the DLL and its library file to the project and freed us from remembering to call the DLL by its name. Another technique consists of calling the DLL by its name. This is referred to as explicit call because you specify the name of the DLL you need and you don't have to copy and paste it in your directory and you don't have to add it to the project.

To call a DLL explicitly,

  • You first call the LoadLibrary() function. Since/if creating an MFC application, Microsoft recommends that you use the AfxLoadLibrary() function
  • To use the function you need from the DLL, call the GetProcAddress() function
  • When you have finished using the DLL, you can call the FreeLibrary() function. This time too, Microsoft recommends using the AfxFreeLibrary() function instead.

 

 

 

Practical Learning: Loading a DLL Explicitly

  1. To start a new application, display the New dialog box and click the Projects property page
  2. Select MFC AppWizard (exe)
  3. In the Name edit box, type ExplicitDLLTest1 and press Enter
  4. In the MFC AppWizard Step 1, click Dialog Based and click Finish then click OK
  5. Delete the TODO line on the dialog box
  6. Add an Edit Box control to the dialog box and change its ID to IDC_NUMBER
  7. Add a new button. Change its ID to IDC_GET_NUMBER_BTN and change its Caption to Get Number
  8. Add a new Edit Box control and change its ID to IDC_GETNUMBER
     
  9. Press Ctrl + W to open ClassWizard and click the Member Variables property page
  10. Add a CString Member Variable for the IDC_GETNUMBER control and name it m_GetNumber
  11. Add a CString Member Variable for the IDC_NUMBER control and name it m_Number
  12. Click the Message Maps tab and, in the Class Name combo box, select CExplicitDLLTest1Dlg. In the Object IDs list, click IDC_GET_NUMBER_BTN
  13. In the Messages list, double-click BN_CLICKED. Accept the suggested name of the function and click OK
  14. Click Edit Code and change the file as follows:
     
    // ExplicitDLLTest1Dlg.cpp : implementation file
    //
    
    #include "stdafx.h"
    #include "ExplicitDLLTest1.h"
    #include "ExplicitDLLTest1Dlg.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    typedef double (*LPGETNUMBER)(double Nbr);
    HINSTANCE hDLL = NULL;
    LPGETNUMBER lpGetNumber;
    
    . . .
    
    /////////////////////////////////////////////////////////////////////////////
    // CExplicitDLLTest1Dlg dialog
    
    CExplicitDLLTest1Dlg::CExplicitDLLTest1Dlg(CWnd* pParent /*=NULL*/)
    	: CDialog(CExplicitDLLTest1Dlg::IDD, pParent)
    {
    	//{{AFX_DATA_INIT(CExplicitDLLTest1Dlg)
    	m_GetNumber = _T("0");
    	m_Number = _T("1");
    	//}}AFX_DATA_INIT
    	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }
    
    void CExplicitDLLTest1Dlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CExplicitDLLTest1Dlg)
    	DDX_Text(pDX, IDC_GETNUMBER, m_GetNumber);
    	DDX_Text(pDX, IDC_NUMBER, m_Number);
    	//}}AFX_DATA_MAP
    }
    
    BEGIN_MESSAGE_MAP(CExplicitDLLTest1Dlg, CDialog)
    	//{{AFX_MSG_MAP(CExplicitDLLTest1Dlg)
    	ON_WM_SYSCOMMAND()
    	ON_WM_PAINT()
    	ON_WM_QUERYDRAGICON()
    	ON_BN_CLICKED(IDC_GET_NUMBER_BTN, OnGetNumberBtn)
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // CExplicitDLLTest1Dlg message handlers
    
    BOOL CExplicitDLLTest1Dlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    
    	// Add "About..." menu item to system menu.
    
    	// IDM_ABOUTBOX must be in the system command range.
    	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    	ASSERT(IDM_ABOUTBOX < 0xF000);
    
    	CMenu* pSysMenu = GetSystemMenu(FALSE);
    	if (pSysMenu != NULL)
    	{
    		CString strAboutMenu;
    		strAboutMenu.LoadString(IDS_ABOUTBOX);
    		if (!strAboutMenu.IsEmpty())
    		{
    			pSysMenu->AppendMenu(MF_SEPARATOR);
    			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    		}
    	}
    
    	// Set the icon for this dialog.  The framework does this automatically
    	//  when the application's main window is not a dialog
    	SetIcon(m_hIcon, TRUE);			// Set big icon
    	SetIcon(m_hIcon, FALSE);		// Set small icon
    	
    	// TODO: Add extra initialization here
    	
    	hDLL = AfxLoadLibrary("ExplicitDLL1");
    
    	if( hDLL == NULL )
    		AfxMessageBox("Could not load the DLL");
    	else
    	{
    	lpGetNumber = (LPGETNUMBER)GetProcAddress(hDLL, "GetNumber");
    	}
    
    	return TRUE;  // return TRUE  unless you set the focus to a control
    }
    
    . . .
    	
    
    void CExplicitDLLTest1Dlg::OnGetNumberBtn() 
    {
    	// TODO: Add your control notification handler code here
    	double Number, GetNbr;
    	UpdateData();
    
    	if( hDLL == NULL )
    	{
    		AfxMessageBox("Could not find the DLL");
    		return;
    	}
    
    	Number = atof(m_Number);
    	GetNbr = lpGetNumber(Number);
    	m_GetNumber.Format("%.2f", GetNbr);
    
    	UpdateData(FALSE);
    }
  15. Test the application:
     
  16. Close the dialog box
 

Previous Copyright © 2004-2006 FunctionX, Inc.