What's the difference between the two?
i.e. for finding functions such as Nt___ or Zw___
In MS Windos, there is a difference between implicit linking and explicit linking.
Implicit Linking
The executable is linked against the accompanying library (.lib
file) which provides the symbols exported from DLL. (The functions for import are remarked with __declspec(dllimport)
.) Implicit linked DLLs are loaded with executable.
Explicit Linking
The program loads a DLL explicitly calling LoadLibrary()
. To call functions of the DLL their address has to be determined using GetProcAddress()
.
However, GetProcAddress()
can be used as well for functions which come from implicit linked DLLs. This can be helpful, if accidentally the same symbol is available in multiple DLLs (e.g. if DLLs have been used which are linked against different runtime DLLs).
Sometimes, DLLs are provided without import libraries. A wellknown example is OpenGL for which MS stopped support with version 1.2. However, with sufficient H/W and up-to-date drivers, all functions of the current OpenGL version might be availabe (and can be loaded with GetProcAdress()
at run-time).
A piece of sample code for OpenGL binding MyGL.cc
:
// version 2.0
glAttachShader
= (PFNGLATTACHSHADERPROC)wglGetProcAddress(
"glAttachShader");
glCompileShader
= (PFNGLCOMPILESHADERPROC)wglGetProcAddress(
"glCompileShader");
glCreateProgram
= (PFNGLCREATEPROGRAMPROC)wglGetProcAddress(
"glCreateProgram");
glCreateShader
= (PFNGLCREATESHADERPROC)wglGetProcAddress(
"glCreateShader");
glDeleteProgram
= (PFNGLDELETEPROGRAMPROC)wglGetProcAddress(
"glDeleteProgram");
glDeleteShader
= (PFNGLDELETESHADERPROC)wglGetProcAddress(
"glDeleteShader");
with MyGL.h
:
// Version 2.0
extern MY_GL_API PFNGLATTACHSHADERPROC glAttachShader;
extern MY_GL_API PFNGLCOMPILESHADERPROC glCompileShader;
extern MY_GL_API PFNGLCREATEPROGRAMPROC glCreateProgram;
extern MY_GL_API PFNGLCREATESHADERPROC glCreateShader;
extern MY_GL_API PFNGLDELETEPROGRAMPROC glDeleteProgram;
extern MY_GL_API PFNGLDELETESHADERPROC glDeleteShader;
where MY_GL_API
is defined as __declspec(dllexport)
when MyGL.dll
is compiled and __declspec(dllimport)
otherwise. (So, actually __declspec(dllimport)
and GetProcAddress()
instead of vs. as function pointers themselves are dllexport
ed but initialized at run-time unsing GetProcAddress()
.)
(The PFNGL
macros expand to function pointer types with the appropriate signature. They are included from a header provided by kronos.org.)
Another important usage of GetProcAddress()
is for functions which may exist not before a certain version of Windows (or other functions which may or may not be available in DLLs). Thus, the application can be written backwards compatible providing an alternative fall-back when GetProcAddress()
fails for the intended function.
The sample provided on MSDN for GetProcAddress()
:
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
// Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
PGNSI pGNSI;
SYSTEM_INFO si;
ZeroMemory(&si, sizeof(SYSTEM_INFO));
pGNSI = (PGNSI) GetProcAddress(
GetModuleHandle(TEXT("kernel32.dll")),
"GetNativeSystemInfo");
if (NULL != pGNSI) {
pGNSI(&si);
} else {
GetSystemInfo(&si);
}
Further reading: MSDN: Link an executable to a DLL