使用 GetProcAddress Function 时,有以下几点需要特别留意:
1. 第二个参数类型是 LPCSTR,不是 ;
2. 用 __declspec(dllexport),按 C 名称修饰(extern "C") 导出的函数名,对于 __stdcall 和 __fastcall 调用约定是相同的;对 __cdecl 是不同的(导出的函数名没有前面的下划线);
3. 即使返回值不是 NULL,也有可能发生错误。当 .def 模块不是连续地从 1 开始编号 ordinal 值,那么,如果用一个无函数对应的 ordinal 值调用 GetProcAddress,就会发生错误,返回一个无效的非 NULL 地址;
4. 最好用函数名,而不是 ordinal 值调用 GetProcAddress,以避免不同版本 Dll 中某些函数不存在的情况。
注:确认 Dll 的导出函数名,可以用 DUMPBIN /EXPORTS dll_file_name.dll 命令,然后查看 name 列。
[cpp]
- // The myPuts function writes a null-terminated string to
- // the standard output device.
-
- // The export mechanism used here is the __declspec(export)
- // method supported by Microsoft Visual Studio, but any
- // other export method supported by your development
- // environment may be substituted.
-
-
- #include <windows.h>
-
- #define EOF (-1)
-
- #ifdef __cplusplus // If used by C++ code,
- extern "C" { // we need to export the C interface
- #endif
-
- __declspec(dllexport) int __cdecl myPuts(LPTSTR lpszMsg) // __cdecl | __stdcall | __fastcall
- {
- DWORD cchWritten;
- HANDLE hStdout;
- BOOL fRet;
-
- // Get a handle to the standard output device.
-
- hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
- if (INVALID_HANDLE_VALUE == hStdout)
- return EOF;
-
- // Write a null-terminated string to the standard output device.
-
- while (*lpszMsg != '\0')
- {
- fRet = WriteFile(hStdout, lpszMsg, 1, &cchWritten, NULL);
- if( (FALSE == fRet) || (1 != cchWritten) )
- return EOF;
- lpszMsg++;
- }
-
- return 1;
- }
-
- #ifdef __cplusplus
- }
- #endif
[cpp]
- // A simple program that uses LoadLibrary and
- // GetProcAddress to access myPuts from Myputs.dll.
-
- #include <stdio.h>
- #include <windows.h>
-
- typedef int (__cdecl *MYPROC)(LPTSTR); // __cdecl | __stdcall | __fastcall
-
- VOID main(VOID)
- {
- HINSTANCE hinstLib;
- MYPROC ProcAdd;
- BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
-
- // Get a handle to the DLL module.
-
- hinstLib = LoadLibrary(TEXT("bin\\Myputs")); // 虽然 MSDN Library 说这里如果
- // 指定了路径,要用 backslashes (\),
- // 不要用 forward slashes (/),但
- // 其实用二者都可以。
- // 注:如果用 \,要用 \\。
-
- // If the handle is valid, try to get the function address.
-
- if (hinstLib != NULL)
- {
- ProcAdd = (MYPROC)GetProcAddress(hinstLib, "myPuts"); // __cdecl : myPuts
- // __stdcall : _myPuts@4
- // __fastcall: @myPuts@4
-
- // If the function address is valid, call the function.
-
- if (NULL != ProcAdd)
- {
- fRunTimeLinkSuccess = TRUE;
- (ProcAdd) (TEXT("Message via DLL function\n"));
- }
-
- // Free the DLL module.
-
- fFreeResult = FreeLibrary(hinstLib);
- }
-
- // If unable to call the DLL function, use an alternative.
-
- if (! fRunTimeLinkSuccess)
- printf("Message via alternative method\n");
- }
原文: