19
votes

i'm wondering why linkers can not do their job simply by consulting the information in the actual .dll files that got the actual implementation code ? i mean why linkers still need .lib files to do implicit linking ?

are not the export and relative address tables enough for such linking ?

is there anyway by which one can do implicit linking using only the .dll without the .lib stub/proxy files ?

i thought the windows executable loader would simply do LoadLibrary/LoadLibraryEx calls on behalf of the program (hence the name implicit linking) which is the main difference to explicit linking. if that is true then doing it explicitly without .lib should indicate that it is doable without it implicitly, right ? or i'm just saying non sense?

1

1 Answers

8
votes

I can think of a a few reasons.

  • Using .lib files mean you can build for a different version of a DLL than you have on your system, provided you just have the correct SDK installed.
  • Compilers & linkers need to support cross-platform compilations - You might be building for a 64-bit target on a 32-bit platform and vice-versa and not have the correct architecture DLL present.
  • .lib files enable you to "hide" certain parts of your implementation - you could have private exports that do not show up in the .lib but are discoverable via GetProcAddress. You can also do ordinal exports in which case they don't have a friendly name exported, but would have a friendly name in the .lib.
  • Native DLL's do not have strong names, so it may be possible to pick up the wrong version of the DLL.
  • And most importantly, this technology was designed in the 1980's. If it were designed today, it'd probably be closer to what you describe - for instance, .NET you just need to reference the target assembly and you have everything you need to use it.

I don't know of any way to do implicit linking solely with the DLL - A quick search revealed several tools, but I haven't used any of them.

In this case, I would create a separate source file with the functions you need to use, and dynamically load the DLL and bind them as needed. For example:

// using global variables and no-error handling for brevity.

HINSTANCE theDll = NULL;
typedef void (__stdcall * FooPtr)();
FooPtr pfnFoo = NULL;
INIT_ONCE initOnce;

BOOL CALLBACK BindDLL(PINIT_ONCE initOnce, PVOID parameter, PVOID context)
{
    theDll = LoadLibrary();
    pfnfoo = GetProcAddress(dll, "Foo");

    return TRUE;
}

// Export for foo
void Foo()
{
    // Use one-time init for thread-safe lazy initialization
    InitOnceExecuteOnce(initOnce, BinDll, NULL, NULL)
    pfnFoo();
}