有效地为不同的Windows版本使用不同的API

Cra*_*ger 2 c windows dll winapi

我面临着在可用的情况下使用新的Windows运行时功能的需要,并且回归到新的运行时功能不存在的情况.

代码路径对性能至关重要.GetSystemTimePreciseAsFileTime如果平台(Windows 8/Windows Server 2012)提供它,我需要打电话,GetSystemTimeAsFileTime如果新版本不存在,我需要回调.

我知道我可以使用LoadLibraryGetProcAddress加载GetSystemTimePreciseAsFileTime,如果失败,请回到GetSystemTimeAsFileTime.我担心通过另一层间接性来调用某些东西作为性能的关键性能影响.

是否有任何内置机制来延迟加载符号,而不是整个DLL?所以我可以在启动时测试Windows版本并调用GetSystemTimePreciseAsFileTime在Win8 上使用的函数,否则调用使用的函数GetSystemTimeAsFileTime,而不会导致整个可执行文件失败并在旧版Windows上出现链接错误?

或者我应该停止担心和使用GetProcAddress

and*_*abs 9

正如对问题的各种评论所说,成本GetProcAddress()很低.通过函数指针调用函数的成本也接近于零.

但是,让我们说我们正在超级批判地工作.我们观察到您要调用的两个函数具有签名

VOID WINAPI GetSystemTimePreciseAsFileTime(LPFILETIME lpSystemTimeAsFileTime);
void WINAPI GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime);
Run Code Online (Sandbox Code Playgroud)

也就是说,它们具有几乎相同的签名; 唯一的区别是奇怪的返回类型VOID...... MSDN所说的只是一个扩展到的宏void,所以它们完全一样.

这是什么意思?这意味着您可以使用单个函数指针变量,在程序开始时初始化一次,如下所示:

// global scope
VOID (*WINAPI myGetSystemTime)(LPFILETIME);

// in your initalization code
FARPROC fp;
myGetSystemTime = GetSystemTimeAsFileTime;
if (/* LoadLibraryW(L"kernel32.dll") worked */) {
    fp = GetProcAddress(/* library handle */, "GetSystemTimePreciseAsFileTime");
    if (fp != NULL)
        myGetSystemTime = (VOID (*WINAPI)(LPFILETIME)) fp;
}
// and don't worry about errors from LoadLibraryW() or GetProcAddress() since we want to use the fallback; you may log a warning if you so choose
Run Code Online (Sandbox Code Playgroud)

然后你需要做的就是(*myGetSystemTime)(&time)在需要选择性地调用函数时调用.没有条件分支或不断轮询DLL,并且应该没有可衡量的性能影响.

  • 如果签名不同,你可以在它们周围放置一个包装函数,并将指针存储到*that*. (3认同)