c – 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在编译MyGL.dll时定义为__declspec(dllexport),否则定义为__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

上一篇:Servlet


下一篇:在Win32环境中从ntdll.dll调用Nt函数,C