Consider the following code which needs to call one of two functions in User32.dll
.
if( IsWindowsVistaOrGreater() )
AddClipboardFormatListener(hWnd) ;
else
SetClipboardViewer(hWnd) ;
If I'm not mistaken, this program will fail to start on WinXP because AddClipboardFormatListener
does not exist in User32.dll
under XP.
One way to solve this is not calling AddClipboardFormatListener
directly but rather get a pointer to it ourselves:
GetProcAddress(GetModuleHandle("User32.dll"), "AddClipboardFormatListener")
.
However, if I instruct the linker to delay-load User32.dll
...
- Would this avoid loading that specific function under XP so that I don't need to call
GetModuleHandle
andGetProcAddress
? - Is it recommended to delay-load a DLL when only a few functions need to be delay-loaded?
The case of User32.dll
is particularly dramatic on the second point since most of the functions used in the program are know to exist in that DLL on all Windows versions.
I would guess that linking at load-time is more efficient than at run-time since the latter needs additional checks before each function call.
But I'm just guessing, hence the question.
Yes. This is exactly the type of situation that delay-loading was invented for. your code can call a DLL function as if it were statically linked, but the executable will not load the DLL function pointer at runtime until the function is actually called for the first time. Internally, the delay-load mechanism uses
LoadLibrary()
andGetProcAddress()
for you.If a DLL is delay-loaded, ALL of its functions are delay-loaded, you cannot pick and choose which ones you want. So, if your app needs to use a lot of functions from the same DLL, like
user32.dll
, then static linking is usually more efficient, and then you can useGetProcAddress()
manually for the few functions you really need to handle differently.In this case, I would suggest getting rid of the OS check altogether and rely only on whether the DLL function actually exists or not, eg:
Where delay-loading really shines is in its hooks. For instance, on earlier systems, you can use a delay-load failure hook to implement your own version of
AddClipboardFormatListener()
, and then your main code can just callAddClipboardFormatListener()
unconditionally on all systems and it won't know the difference. For example (just a demo, not actually tested):