我用高级语言编程" (Nim),我必须"去C"出于性能原因。我想做这样的事情:
/* Pseudocode */
include <VersionHelpers.h>
/* ...*/
if (isWindows8OrGreater()) {
/** use InterlockedIncrementNoFence64() */
} else {
/** use InterlockedIncrement64() ;( */
}
但我被告知它会在Windows 7上崩溃,因为如果我引用InterlockedIncrementNoFence64(),它必须是可用的,即使我没有尝试调用它。
我正在编写一个多线程应用程序,并使用&#34;消息&#34;实现通信。 (即使在同一个线程内)。这将针对每条消息进行调用,因此内存屏障会对性能产生重大影响。
我已经习惯了Java,在那里工作的东西,以及如何在C中完成。
答案 0 :(得分:2)
具体案例InterlockedIncrementNoFence64
未从任何dll导入,而是在大多数平台上使用编译器内在函数实现( x86 - 通过_InterlockedCompareExchange64
, amd64 - _InterlockedIncrement64
, arm / arm64 - _InterlockedIncrement64_nf
)。因此具有此具体调用的代码将适用于任何Windows版本(当然也在win7中)。
在更一般的情况下,如果我们需要使用几个不在所有操作系统上导出的函数 - 我们可以将它声明为函数指针并在运行时解析。例如,让LoadPackagedLibrary
api
我们可以声明函数指针:
HMODULE (WINAPI * LoadPackagedLibraryAddr)(
_In_ LPCWSTR lpwLibFileName,
_Reserved_ DWORD Reserved
);
在运行时解决它:
*(void**)&LoadPackagedLibraryAddr = GetProcAddress(
GetModuleHandleW(L"kernel32"), "LoadPackagedLibrary");
并使用:
if (LoadPackagedLibraryAddr)
{
LoadPackagedLibraryAddr(L"***",0);
}
else {...}
使用__declspec(dllimport)
声明的函数的另一种可能方式(使用此前缀声明的大多数windows api)使用下一个语法:
extern "C" {
PVOID __imp_LoadPackagedLibrary;
}
#ifdef _M_IX86
__pragma(comment(linker, "/alternatename:__imp__LoadPackagedLibrary@8=___imp_LoadPackagedLibrary"))
#endif
__imp_LoadPackagedLibrary = GetProcAddress(
GetModuleHandleW(L"kernel32"), "LoadPackagedLibrary");
#pragma warning(disable : 4551)
if (LoadPackagedLibrary)//if (__imp_LoadPackagedLibrary)
{
LoadPackagedLibrary(L"***",0);
}
然而,两种方式都生成绝对相同的二进制代码,只使用不同的语法。
注意,根本不需要查询windows版本,只需要尝试获取指向api的指针。或者我们得到它,可以使用,或者不使用。使用__declspec(selectany)
或#pragma comment(linker, "/alternatename:_pWeakValue=_pDefaultWeakValue")
在这里不起作用,因为我们在链接时解析符号(结果对于所有Windows版本都是常见的),但我们实际上需要在运行时解析符号强>