views:

40

answers:

1

Hi.

I'm writing a proxy library (called Library A) that is just an interface to another DLL (called Library B) that may be present or not on the system. The idea is that a program would link to this library A instead of the original library B ; and Library A would handle the errors if Library B wasn't installed on the system.

So a typical proxy function would look like this:

int function(int arg1, int arg2)
{
    HINSTANCE hinstLib;
    UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
    SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
    hinstLib = LoadLibrary(TEXT(ORIGINAL_DLL));
    SetErrorMode (errormode);
    if (hinstLib != NULL)
    {
        ProcAdd = (void *) GetProcAddress(hinstLib, TEXT("function"));
        if (NULL != ProcAdd)
        {
            return (ProcAdd) (arg1, arg2);
        }
        FreeLibrary(hinstLib);
    }
    return ERROR;
}

Now, I would do this for all original entries in Library B. There could be a lot of calls to it. So loading / unloading the DLL so frequently is certainly going to have an impact speed-wise.

I was wondering if it would be acceptable to use a global variable hinstLib ; something like

HINSTANCE hinstLib = LoadLibrary(TEXT(ORIGINAL_DLL));

int function(int arg1, int arg2)
{
    if (hinstLib != NULL)
    {
        ProcAdd = (void *) GetProcAddress(hinstLib, TEXT("function"));
        if (NULL != ProcAdd)
        {
            return (ProcAdd) (arg1, arg2);
        }
    }
    return ERROR;
}

And let Windows automatically unload the DLL when the program exits (assuming it does unload it).

Thanks in advance for your wise remarks...

Jean-Yves

+1  A: 

Unless the unloading is particular use case, then this is fine. However I would implement some thread safety to ensure that there are no race conditions through this code using a Critical Section.

This is simillar example to the one from the wikipedia article

    /* Sample C/C++, Windows, link to kernel32.dll */
    #include <windows.h>

    static CRITICAL_SECTION cs;

    static HINSTANCE hinstLib = LoadLibrary(TEXT(ORIGINAL_DLL));

    /* Initialize the critical section before entering multi-threaded context. */
    InitializeCriticalSection(&cs);

    void f() {
        /* Enter the critical section -- other threads are locked out */
        __try {
           EnterCriticalSection(&cs);

           if (hinstLib != NULL)     {
           ProcAdd = (void *) GetProcAddress(hinstLib, TEXT("function"));
         } __finally { 
            LeaveCriticalSection(&cs);
         }
         if (NULL != ProcAdd) {
               return (ProcAdd) (arg1, arg2);
         }
    }

.
.
.

    /* Release system object when all finished -- usually at the end of the cleanup code */
    DeleteCriticalSection(&cs);
Preet Sangha
That was fast.. I can not easily add a cleanup code however ; because I do not want to modify in any ways the original code that was calling Library B (and will now call Library A). If I could, I would have done the FreeLibrary there..
jyavenard
Using pthreads.h and lock would be trivial to prevent racing conditions. Need to find out if similar APIs exist under Windows. I'm no Windows expert.
jyavenard
see here http://stackoverflow.com/questions/2150938/can-i-get-cs-pthread-h-to-compile-in-windows
Preet Sangha
Regarding critical sections. What happens if DeleteCriticalSection isn't called once the program terminates? Is its call compulsory?
jyavenard