В MS Windos существует разница между неявным связыванием и явным связыванием .
Неявное связывание
Исполняемый файл связан с прилагаемой библиотекой (файл .lib
), которая предоставляет символы, экспортированные из DLL. (Функции для импорта отмечены __declspec(dllimport)
.) Неявно связанные DLL загружаются с исполняемым файлом.
Явная ссылка
Программа загружает DLL, явно вызывающую LoadLibrary()
. Для вызова функций DLL их адрес должен быть определен с помощью GetProcAddress()
.
Однако, GetProcAddress()
может также использоваться для функций, которые происходят из неявно связанных DLL. Это может быть полезно, если случайно один и тот же символ доступен в нескольких библиотеках DLL (например, если использовались библиотеки DLL, которые связаны с различными библиотеками времени выполнения).
Иногда библиотеки DLL предоставляются без библиотек импорта. Хорошо известным примером является OpenGL, для которого MS перестала поддерживать версию 1.2. Однако при наличии достаточного количества H / W и современных драйверов все функции текущей версии OpenGL могут быть доступны (и могут быть загружены с помощью GetProcAdress()
во время выполнения).
Часть примера кода для привязки OpenGL 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");
с 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;
, где MY_GL_API
определяется как __declspec(dllexport)
при компиляции MyGL.dll
и __declspec(dllimport)
в противном случае. (Таким образом, на самом деле __declspec(dllimport)
и GetProcAddress()
вместо против , поскольку сами указатели функций dllexport
редактируются, но инициализируются во время выполнения unsing GetProcAddress()
.)
(Макросы PFNGL
расширяются до типов указателей на функции с соответствующей подписью. Они включены в заголовок, предоставленный kronos.org .)
Другое важное использование GetProcAddress()
предназначено для функций, которые могут существовать не до определенной версии Windows (или других функций, которые могут или не могут быть доступны в DLL). Таким образом, приложение может быть написано с обратной совместимостью, обеспечивая альтернативный запасной вариант, если GetProcAddress()
не подходит для предполагаемой функции.
Пример, предоставленный в MSDN для 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);
}
Дополнительное чтение: MSDN: связать исполняемый файл с DLL