GetProcAddress与__declspec(dllimport)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GetProcAddress与__declspec(dllimport)相关的知识,希望对你有一定的参考价值。

这两者有什么区别?

即用于查找Nt___或Zw___等功能

答案

在MS Windos中,隐式链接和显式链接之间存在差异。

隐式链接

可执行文件链接到附带的库(.lib文件),该库提供从DLL导出的符号。 (导入的函数用__declspec(dllimport)标记。)隐式链接的DLL加载了可执行文件。

显式链接

该程序加载一个显式调用LoadLibrary()的DLL。要调用DLL的函数,必须使用GetProcAddress()确定其地址。

但是,GetProcAddress()也可以用于来自隐式链接DLL的函数。如果在多个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()而不是vs作为函数指针本身是dllexported但在运行时未初始化的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: Link an executable to a DLL

另一答案

GetProcAddress()允许您在运行时查找函数。它对于可选导入或可动态加载的插件等很有用。它的另一个用途是导出的未记录的函数,但没有头文件或库文件。

使用__declspec( dllimport )将该函数添加到导入表中,以便随可执行文件自动加载。

以上是关于GetProcAddress与__declspec(dllimport)的主要内容,如果未能解决你的问题,请参考以下文章

GetProcAddress 使用注意事项

__declspec(dllexport) 静态链接库到 dll

__declspec(dllexport) 和 __declspec(dllimport)的区别

_declspec(dllexport)和.def(转)

转载 __declspec(dllexport) 和__declspec(dllimport)

dllimport与dllexport作用与区别