Tag Archives: dynamic linking

Template Class for Dynamic Linking

Dynamic linking (or runtime linking) is the method of finding and calling a function in a DLL at runtime. The most common use for it is when you can’t be certain that the DLL or function will exist. For example, if you calling a new WINAPI function which only exists in Vista, but you want your application to still run on XP, you will need to use dynamic linking.

The process is simple: load the DLL, get the address of the function and make the call. You need just 3 WNAPI calls to get the job done. Of course, there is error checking too, so a typical function call requires several lines of code, and if you want to save the pointer for use later, you still have worry about keeping track of the handle to the DLL and releasing it when you are done.

So I made a template class to encapsulate the entire process, creating essentially a smart pointer for dynamic functions.

template <typename FunctionPtr> class CDynamicFunction
{
public:
    // Constructor automatically binds the function.
    CDynamicFunction(CString dllName, CString procName)
    {
        _module = ::LoadLibrary(dllName);
        if (_module == NULL)
        {
            // error, DLL probably doesn't exist
            _procAddress = NULL;
        }
        else
        {
            // Get the function pointer - this will be NULL if the function doesn't exist.
            _procAddress = (FunctionPtr)(::GetProcAddress(_module,procName));
        }
    }

    // Destructor automatically releases the DLL.
    virtual ~CDynamicFunction(void)
    {
        if (_module != NULL)
        {
            ::FreeLibrary(_module);
            _module = NULL;
        }
    }

    // Use this method like a regular function. Check for NULL first, in case the function
    // couldn't be linked.
    virtual operator FunctionPtr()
    {
        return _procAddress;
    }

private:
    HMODULE     _module;
    FunctionPtr _procAddress;
};

To use the template class do the following:

1. Typedef a pointer to the function you want to import. The syntax below is for a Windows API call, but you can define it as needed.

typedef LONG (WINAPI *pMyEntryPoint) (HWND hwnd, int xyz);

2. Instantiate the class either in a local stack frame, or in another class. The DLL is loaded upon instantiation and it will be automatically unloaded when the class goes out of scope.

CDynamicFunction<pMyEntryPoint> myEntryPoint("blah.dll", "MyEntryPoint");

3. Check the result of the class and call your function:

if(myEntryPoint == NULL)
{
    // handle error
}
else
{
    LONG result = myEntryPoint(hwnd, x);
}

Simple and reliable, and it avoids the common errors that come from writing the same code in many different places.