GetProcAddress 使用注意事项

使用 GetProcAddress Function 时,有以下几点需要特别留意:

1. 第二个参数类型是 LPCSTR,不是 LPCTSTR

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 列。

// 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 
 
#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
// A simple program that uses LoadLibrary and 
// GetProcAddress to access myPuts from Myputs.dll. 
 
#include  
#include  
 
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"); 
}

你可能感兴趣的:(Windows,C/C++,MSDN,Library)