如何在C ++中使用LoadLibrary(..)调用kernel32.dll函数GetTickCount()

时间:2011-07-02 12:38:50

标签: winapi time

我正在寻找一个在Windows机器上以毫秒为单位获取时间的函数。本质上,我想调用这个WinAPI函数GetTickCount(),但我坚持“使用LoadLibrary(...)n调用GetTickCount()函数”部分..

我搜索了每个论坛用谷歌搜索它但是到处都有人使用了不能编译的不完整代码。任何人都可以编写一个简短的示例程序来加载kernel32.dll并调用GetTickCount()以毫秒显示时间吗?

请编写编译的代码!

4 个答案:

答案 0 :(得分:5)

您应该做的第一件事是声明一个与导出函数兼容的函数指针类型。做到这一点至关重要,也是遇到麻烦的最大可能性。仔细查看函数声明以获得此结果:

 typedef DWORD (WINAPI * GetTickCount_t)(void);

接下来,使用LoadLibrary和GetProcessAddress来获取函数指针值。您始终必须将GPA的返回值强制转换为函数指针类型。像这样:

HMODULE hKernel = LoadLibrary(L"kernel32.dll");
assert(hKernel);
GetTickCount_t pfnGetTickCount = (GetTickCount_t)GetProcAddress(hKernel, "GetTickCount");
assert(pfnGetTickCount);

这里的失败模式是DLL的路径。我没有必要指定一个,因为kernel32.dll存储在c:\ windows \ system32中,这是一个始终位于搜索路径中的目录。对于您自己的DLL,通常情况并非如此。只将它存储在与主EXE相同的目录中,只允许指定DLL文件名而不是完整路径。查看SetDllDirectory()的文档以获取背景信息。

导出函数的名称。这里很容易,Windows API函数以未修饰的名称导出。对于您自己的DLL通常不是这种情况,如果您没有使用extern“C”声明函数并使用C ++编译器,则可以使用前导下划线,“@nn”后缀或错误名称导出导出。要查看真实姓名,请在DLL上使用Dumpbin.exe / exports。另请注意,GetProcAddress使用const char *,与使用Unicode字符串的其他Windows API不同。字符串文字上没有L前缀。

然后你称之为,这很容易:

DWORD tick = pfnGetTickCount();

如果您的函数指针类型声明错误,那么您可能会使AV程序崩溃,获得奇怪的函数结果或不平衡的堆栈。

答案 1 :(得分:1)

您无法加载kernel32.dll,它已经加载到每个进程中。每个版本的Windows都存在GetTickCount,因此您无需GetProcAddress查看它是否存在。您所需要的只是:

#include <windows.h>
#include <iostream>

int main(void)
{
    std::cout << GetTickCount() << std::endl;
}

动态加载示例(因为winmm.dll未预加载):

#include <windows.h>
#include <iostream>

int main(void)
{
    HMODULE winmmDLL = LoadLibraryA("winmm.dll");

    if (!winmmDLL) {
        std::cerr << "LoadLibrary failed." << std::endl;
        return 1;
    }

    typedef DWORD (WINAPI *timeGetTime_fn)(void);
    timeGetTime_fn pfnTimeGetTime = (timeGetTime_fn)GetProcAddress(winmmDLL, "timeGetTime");

    if (!pfnTimeGetTime) {
        std::cerr << "GetProcAddress failed." << std::endl;
        return 2;
    }

    std::cout << (*pfnTimeGetTime)() << std::endl;
    return 0;
}

我使用Visual Studio 2010命令提示符成功编译并运行此示例,不需要特殊的编译器或链接器选项。

答案 2 :(得分:0)

你不必。 Kernel32.dll被加载到Windows上的每个x86进程中。您只需要包含标题以使其正常工作 - 编译器将为您加载它。

答案 3 :(得分:0)

[kernel32.dll]在每个进程中都会被加载,因为它提供了ExitProcess函数...

您只需要包含<windows.h>并致电GetTickCount

干杯&amp;第h。,