Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 有效地为不同的Windows版本使用不同的API_C_Windows_Winapi_Dll - Fatal编程技术网

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

C 有效地为不同的Windows版本使用不同的API,c,windows,winapi,dll,C,Windows,Winapi,Dll,我面临着在可用的情况下使用新的Windows运行时函数的需要,而在新函数不存在的情况下,我需要使用旧的Windows运行时函数 代码路径对性能至关重要。如果平台(Windows 8/Windows Server 2012)提供,我需要调用GetSystemTimePreciseSFileTime,如果新版本不存在,则返回到GetSystemTimeAsFileTime 我知道我可以使用LoadLibrary和GetProcAddress来加载GetSystemTimePrecisesFileTi

我面临着在可用的情况下使用新的Windows运行时函数的需要,而在新函数不存在的情况下,我需要使用旧的Windows运行时函数

代码路径对性能至关重要。如果平台(Windows 8/Windows Server 2012)提供,我需要调用
GetSystemTimePreciseSFileTime
,如果新版本不存在,则返回到
GetSystemTimeAsFileTime

我知道我可以使用
LoadLibrary
GetProcAddress
来加载
GetSystemTimePrecisesFileTime
,如果失败,请返回到
GetSystemTimeAsFileTime
。我关心的是,将这样的东西称为性能关键的东西会对性能产生影响,尽管这是另一个间接层

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


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

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

但我们可以说,我们的工作是超批判性的。我们注意到您要调用的两个函数都有签名

VOID WINAPI GetSystemTimePreciseAsFileTime(LPFILETIME lpSystemTimeAsFileTime);
void WINAPI GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime);
也就是说,他们的签名几乎相同;唯一的区别是奇怪的返回类型
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

然后,当需要有选择地调用函数时,只需调用
(*myGetSystemTime)(&time)
。没有条件分支或不断轮询DLL,应该没有可测量的性能影响。

我认为andlabs的答案可能是正确的;通过指针调用函数的性能损失不大。另一方面,它确实需要额外的RAM往返(或者导致指针占用缓存中可能更好使用的一行),因此它不是绝对确定的


如果配置文件显示您确实存在问题,请考虑将性能关键代码放入DLL中。有两个DLL版本,每个API一个。安装应用程序后,请将适当的版本放到适当的位置。

我会说“不要担心,使用GetProcAddress”。额外的间接寻址可能非常小。尝试进入GetSystemTimeAsFileTime,一次使用GetProcAddr,一次不使用,可能几乎没有区别。没有“间接寻址层”。否则,一个探查器或一个小测试程序可以很容易地向您展示一些东西。为什么您会担心一个函数调用的性能,这个函数在启动时调用了两次,以后就再也不会运行了?如果签名不同,您可以在其周围放置一个包装函数,并存储指向它的指针。