Thursday, April 5, 2012

Import native DLL into a C++ program

When you are writing C++ programs, sometimes you may need to use third party dll files in your application. This tutorial is a comprehensive guide to using a native dll within a C++ application. Before we start the coding, let's have a small introduction about dynamic loading.


What is Dynamic Loading?

Normally, when you link to a DLL via a LIB file (for example, the MFC DLLs), the DLL is loaded when your application starts up. This kind of loading is referred to as implicit linking, because the system takes care of the DLL loading for you - all you have to do is link with the LIB file.

Dynamic loading (a.k.a. dynamic linking) means that your application loads a DLL just before you call a function in the DLL. For dynamic loading, you do not use a LIB file. Instead, what you do is call a pair of Win32 API functions (LoadLibrary/GetProcAddress) that load the DLL and then retrieve the address of a function in the DLL. Because you explicitly invoke these APIs, this kind of loading is also referred to as explicit linking. To summarize:


  • implicit linking - DLL is loaded automatically when your app starts
  • explicit linking - you write code to load DLL

following acronyms are used in the programming world for these two types of linking.

static linking - static loading, static linking, implicit linking, implicit loading, automatic loading

dynamic linking - dynamic loading, explicit linking, explicit loading, manual loading

Why Use Dynamic Loading?

Before I get into the details of dynamically loading DLLs, let me first answer the question: When is it desirable to dynamically load a DLL? Here are the typical scenarios:


  • You don't have a lib file to link with - this is a pretty lame reason, since if you worked at it you could generate a LIB file. On the whole, though, generating a LIB file is probably more work than just using LoadLibrary/GetProcAddress to dynamically load a DLL.

  • A DLL may not always be present - if you want to provide for some graceful program degradation, you must dynamically load any DLL that may or may not be present on the target machine (example: UXTHEME.DLL, which exists only on XP). If you used implicit linking, your application would never have the chance to degrade gracefully - the system simply would not allow your app to start, and would instead display some alarming message to your user.

  • You need to support multiple feature sets - this is one of the historically valid reasons for using dynamic loading. If you have a product that supports many different features, and you want to load only those features that the customer has paid for, then what you do is package each feature set in its own DLL, and ship the DLL to the customer when he orders it. This is also a very convenient way to add new features (read: plug-ins) to your product, essentially making it open-ended.

  • You need to support multiple platforms - this is also one of the historically valid reasons for using dynamic loading. You need to support multiple platforms (Win98, Win2000, WinXP) and each platform requires slightly different code for some reason. A simple solution is to segregate the code for each platform in its own DLL.

  • You need to speed up the time it takes to load your application - this is another historical reason for using dynamic loading. You will start thinking about this when customers start complaining about how slow your app is to load. The idea is to identify what DLLs are necessary to display the core UI, and then dynamically load all the other DLLs that your app needs.

How to implement with in the code?

Let's start the actual coding. Let's say you have a dll file which is named as mylibrary.dll. You have so many methods inside that library. You need to use the method Start(BOOL id) within your application.

Define a constant name for your dll file. (This is optional)
#define MY_LIBRARY_NAME TEXT("mylibrary.dll")

Declare a Handle for the library file instance.
HINSTANCE g_hinstLibrary;

Define a function pointer to the method you are willing to call from the dll. Signature of the definition should be equal as the actual method.

typedef BOOL (__stdcall *LPFN_START)(BOOL);

Declare a variable of the defined function pointer type
LPFN_START g_sStart;

Load the library file into the instance variable
g_hinstLibrary = ::LoadLibrary(MY_LIBRARY_NAME);

Get the Process address of the specific method you are going to use in your application

if (NULL != g_hinstLibrary)
{
//Get API addresses
g_sStart = (LPFN_START )GetProcAddress((HMODULE)g_hinstLibrary, TEXT("Start"));
          }

Now you can call the Start(BOOL id) function within your applications main method (or any other method) as below.

if(NULL != g_sStart)
{
      g_sStart(10);
}


Once you are finished using the function, Release the loaded library

if (NULL != g_hinstLibrary)
{
FreeLibrary(g_hinstLibrary);
}

This blog has helped me to write this post and some of the sections are copied from there.


Cheers !!!!!!!!!!!!!




No comments:

Post a Comment