GetProcAddress vs __declspec (dllimport) - PullRequest
0 голосов
/ 15 сентября 2018

Какая разница между этими двумя?

т.е. для поиска таких функций, как Nt___ или Zw ___

Ответы [ 2 ]

0 голосов
/ 15 сентября 2018

В 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

0 голосов
/ 15 сентября 2018

GetProcAddress() позволяет найти функции во время выполнения. Это полезно для необязательного импорта или для таких вещей, как плагины, которые могут загружаться динамически. Другое использование для этого для недокументированных функций, которые экспортируются, но не имеют файла заголовка или файла библиотеки.

Использование __declspec( dllimport ) добавляет функцию в таблицу импорта, чтобы она автоматически загружалась вместе с исполняемым файлом.

...