首页 > 代码库 > Windows程序中加载并使用动态链接库

Windows程序中加载并使用动态链接库

1 GetProcAddress()

1.1函数原型

GetProcAddress函数检索指定的动态链接库(DLL)中的输出库函数地址。

函数原型:
FARPROC GetProcAddress(
HMODULE hModule, // DLL模块句柄
LPCSTR lpProcName // 函数名
);
hModule
[in] 包含此函数的DLL模块的句柄。LoadLibrary、 AfxLoadLibrary  或者GetModuleHandle函数可以返回此句柄。
lpProcName
[in] 包含函数名的以NULL结尾的字符串,或者指定函数的序数值。如果此参数是一个序数值,它必须在一个字的底字节,高字节必须为0。
返回值:
如果 函数调用成功,返回值是DLL中的输出函数地址。
如果 函数调用失败,返回值是NULL。得到进一步的 错误信息,调用函数GetLastError。

1.2 注释

GetProcAddress函数被用来检索在DLL中的输出函数地址。
lpProcName 指针指向的函数名,拼写和大小写必须和DLL 源代码中的 模块定义文件(.DEF)中输出段(EXPORTS)中指定的相同。Win32 API函数的输出名可能不同于你在代码中调用的这些函数名,这个不同被宏隐含在相关的SDK头文件中。如果想得到更多信息,请参考Win32函数原型(Win32 Function Prototypes)。
lpProcName参数能够识别DLL中的函数,通过指定一个与函数相联系的序数值(在.DEF中的EXPORTS段)。GetProcAddress函数验证那个指定的序数值是否在输出的序数1和最高序数值之间(在.DEF中)。函数用这个序数值作为索引从函数表中读函数地址,假如.DEF 文件不连续地定义函数的序数值,如从1到N(N是输出的函数序数值),错误将会发生,GetProcAddress将会返回一个错误的、非空的地址,虽然指定的序数没有对应的函数。
为了防止函数不存在,函数应该通过名字指定而不是序数值。
要求:
Windows NT/2000: 要求 Windows NT 3.1  或以后版本。
Windows 95/98: 要求Windows 95 或以后版本。
头文件: 在Winbase.h中声明,include Windows.h。
库文件: Use Kernel32.lib。

1.3 参考代码

动态链接库纵览( Dynamic-Link Libraries  Overview), 动态链接库函数(Dynamic-Link Library Functions),FreeLibrary, GetModuleHandle, LoadLibrary
示例代码:
调用KERNEL32.DLL中的RegisterServiceProcess(仅在Windows98中适用)
HMODULE hModule=GetModuleHandle("kernel32.dll");
if (hModule)
  {
  typedef DWORD (CALLBACK *LPFNREGISTER)(DWORD,DWORD);
  LPFNREGISTER lpfnRegister;
  lpfnRegister=(LPFNREGISTER)GetProcAddress(hModule,"RegisterServiceProcess");
  if (lpfnRegister)
  {
  (*lpfnRegister)(NULL,1L);
  }
  }

 2 LoadLibrary()

HMODULE WINAPI LoadLibrary( _In_ LPCTSTR lpFileName);
Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
载入指定的 动态链接库,并将它映射到当前进程使用的 地址空间。一旦载入,即可访问库内保存的资源
Long,成功则返回库模块的句柄,零表示失败。会设置GetLastError
参数 类型及说明
lpLibFileName String,指定要载入的 动态链接库的名称。采用与CreateProcess函数的lpCommandLine参数指定的同样的搜索顺序
注解
一旦不需要,用FreeLibrary函数释放DLL

3 FreeLibrary()

Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. When the reference count reaches zero, the module is unloaded from the address space of the calling process and the handle is no longer valid.

3.1 函数原型

BOOL WINAPI FreeLibrary(
  _In_  HMODULE hModule
);

 Parameters
hModule  [in]

A handle to the loaded library module. The LoadLibrary, LoadLibraryEx, GetModuleHandle, or GetModuleHandleEx function returns this handle.

Return value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call the GetLastError function.

3.2 注释

The system maintains a per-process reference count for each loaded module. A module that was loaded at process initialization due to load-time dynamic linking has a reference count of one. The reference count for a module is incremented each time the module is loaded by a call to LoadLibrary. The reference count is also incremented by a call to LoadLibraryEx unless the module is being loaded for the first time and is being loaded as a data or image file.

The reference count is decremented each time the FreeLibrary or FreeLibraryAndExitThread function is called for the module. When a module‘s reference count reaches zero or the process terminates, the system unloads the module from the address space of the process. Before unloading a library module, the system enables the module to detach from the process by calling the module‘s DllMain function, if it has one, with the DLL_PROCESS_DETACH value. Doing so gives the library module an opportunity to clean up resources allocated on behalf of the current process. After the entry-point function returns, the library module is removed from the address space of the current process.

It is not safe to call FreeLibrary from DllMain. For more information, see the Remarks section in DllMain.

Calling FreeLibrary does not affect other processes that are using the same module.

Use caution when calling FreeLibrary with a handle returned by GetModuleHandle. The GetModuleHandle function does not increment a module‘s reference count, so passing this handle to FreeLibrary can cause a module to be unloaded prematurely.

A thread that must unload the DLL in which it is executing and then terminate itself should call FreeLibraryAndExitThread instead of calling FreeLibrary and ExitThread separately. Otherwise, a race condition can occur. For details, see the Remarks section of FreeLibraryAndExitThread.

 

Windows程序中加载并使用动态链接库