Link an executable to a DLL (original) (raw)

An executable file links to (or loads) a DLL in one of two ways:

An executable can use either linking method to link to the same DLL. Furthermore, these methods aren't mutually exclusive; one executable may implicitly link to a DLL, and another might attach to it explicitly.

Determine which linking method to use

Whether to use implicit linking or explicit linking is an architectural decision you must make for your application. There are advantages and disadvantages to each method.

Implicit Linking

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.

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.

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 can't 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 address space.

If any of the DLLs has an entry-point function for initialization and termination code such as DllMain, 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 doesn't 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.

Like the rest of a program's code, the loader maps DLL code into the address space of the process when the process starts up. The operating system loads it into memory only when needed. As a result, the PRELOAD and LOADONCALL code attributes used by .def files to control loading in previous versions of Windows no longer have meaning.

Explicit Linking

Most applications use implicit linking because it's the easiest linking method to use. However, there are times when explicit linking is necessary. Here are some common reasons to use explicit linking:

Here are two hazards of explicit linking to be aware of:

How to use implicit linking

To use a DLL by implicit linking, client executables must obtain these files from the provider of the DLL:

To use the data, functions, and classes in a DLL by implicit linking, any client source file must include the header files that declare them. From a coding perspective, calls to the exported functions are just like any other function call.

To build the client executable file, you must link with the DLL's import library. If you use an external makefile or build system, specify the import library together with the other object files or libraries that you link.

The operating system must be able to locate the DLL file when it loads the calling executable. That means you must either deploy or verify the existence of the DLL when you install your application.

To use a DLL by explicit linking, applications must make a function call to explicitly load the DLL at run time. To explicitly link to a DLL, an application must:

For example, this sample function calls LoadLibrary to load a DLL named "MyDLL", calls GetProcAddress to obtain a pointer to a function named "DLLFunc1", calls the function and saves the result, and then calls FreeLibrary to unload the DLL.

#include "windows.h"

typedef HRESULT (CALLBACK* LPFNDLLFUNC1)(DWORD,UINT*);

HRESULT LoadAndCallSomeFunction(DWORD dwParam1, UINT * puParam2)
{
    HINSTANCE hDLL;               // Handle to DLL
    LPFNDLLFUNC1 lpfnDllFunc1;    // Function pointer
    HRESULT hrReturnVal;

    hDLL = LoadLibrary("MyDLL");
    if (NULL != hDLL)
    {
        lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, "DLLFunc1");
        if (NULL != lpfnDllFunc1)
        {
            // call the function
            hrReturnVal = lpfnDllFunc1(dwParam1, puParam2);
        }
        else
        {
            // report the error
            hrReturnVal = ERROR_DELAY_LOAD_FAILED;
        }
        FreeLibrary(hDLL);
    }
    else
    {
        hrReturnVal = ERROR_DELAY_LOAD_FAILED;
    }
    return hrReturnVal;
}

Unlike this example, in most cases you should call LoadLibrary and FreeLibrary only once in your application for a given DLL. It's especially true if you're going to call multiple functions in the DLL, or call DLL functions repeatedly.

What do you want to know more about?

See also

Create C/C++ DLLs in Visual Studio