Cet*_*ert 5 c macros conditional-compilation c-preprocessor
Windows仅向Windows Vista提供GetTickCount,并从该操作系统开始提供GetTickCount64.如何通过调用不同的函数来编译C程序?
如何让C编译器检查是否在包含的头文件中声明了一个函数,并根据该特定函数是否可用来编译代码的不同部分?
#if ??????????????????????????????
unsigned long long get_tick_count(void) { return GetTickCount64(); }
#else
unsigned long long get_tick_count(void) { return GetTickCount(); }
#endif
Run Code Online (Sandbox Code Playgroud)
寻找工作样本文件而不仅仅是提示.
编辑:我在(64位)Windows 7 RC上使用minGW中的gcc 3.4.5尝试了以下操作,但它没有帮助.如果这是MinGW问题,我该如何解决这个问题?
#include <windows.h>
#if (WINVER >= 0x0600)
unsigned long long get_tick_count(void) { return 600/*GetTickCount64()*/; }
#else
unsigned long long get_tick_count(void) { return 0/*GetTickCount()*/; }
#endif
Run Code Online (Sandbox Code Playgroud)
RBe*_*eig 13
根据目标Windows版本编译API的时间选择将构建的可执行文件锁定到该版本和更新版本.这是开源,*nix目标项目的常用技术,假定用户将为其平台配置源工具包并编译干净以进行安装.
在Windows上,这不是通常的技术,因为假设最终用户根本没有编译器通常是不安全的,更不用说想要处理构建项目的复杂性了.
通常,只使用所有Windows版本中存在的旧API就足够了.这也很简单:您只需忽略新API的存在.
如果这还不够,您可以使用LoadLibrary()和GetProcAddress()尝试在运行时解析新符号.如果无法解决,那么您将回退到较旧的API.
这是一个可能的实现.它会检测第一个调用,并尝试加载库并解析名称"GetTickCount64".在所有调用中,如果指向已解析符号的指针为非null,则调用它并返回结果.否则,它会回退到较旧的API,转换其返回值以匹配包装器的类型.
unsigned long long get_tick_count(void) {
static int first = 1;
static ULONGLONG WINAPI (*pGetTickCount64)(void);
if (first) {
HMODULE hlib = LoadLibraryA("KERNEL32.DLL");
pGetTickCount64 = GetProcAddressA(hlib, "GetTickCount64");
first = 0;
}
if (pGetTickCount64)
return pGetTickCount64();
return (unsigned long long)GetTickCount();
}
Run Code Online (Sandbox Code Playgroud)
请注意,我使用了... API函数的一种风格,因为已知库名称和符号名称只是ASCII ...如果使用此技术从可能位于文件夹中的已安装DLL加载符号以非ASCII字符命名,那么您将需要担心使用Unicode构建.
这是未经测试的,您的里程会有所不同等等......
之前的答案已经指出检查针对您的特定情况出现的特定#define。这个答案适用于编译不同代码的更一般情况,无论函数是否可用。
与尝试在 C 文件本身中完成所有操作不同,这才是配置脚本真正发挥作用的地方。如果您在 Linux 上运行,我会毫不犹豫地向您推荐GNU Autotools 。我知道有适用于 Windows 的端口,至少如果您使用 Cygwin 或 MSYS,但我不知道它们有多有效。
一个简单的(而且非常丑陋的)脚本,如果你有 sh 就可以工作(我没有方便的 Windows 设置来测试它),它看起来像这样:
#!/bin/sh
# First, create a .c file that tests for the existance of GetTickCount64()
cat >conftest.c <<_CONFEOF
#include <windows.h>
int main() {
GetTickCount64();
return 0;
}
_CONFEOF
# Then, try to actually compile the above .c file
gcc conftest.c -o conftest.out
# Check gcc's return value to determine if it worked.
# If it returns 0, compilation worked so set CONF_HASGETTICKCOUNT64
# If it doesn't return 0, there was an error, so probably no GetTickCount64()
if [ $? -eq 0 ]
then
confdefs='-D CONF_HASGETTICKCOUNT64=1'
fi
# Now get rid of the temporary files we made.
rm conftest.c
rm conftest.out
# And compile your real program, passing CONF_HASGETTICKCOUNT64 if it exists.
gcc $confdefs yourfile.c
Run Code Online (Sandbox Code Playgroud)
这应该很容易翻译成您选择的脚本语言。如果您的程序需要额外的包含路径、编译器标志或其他内容,请确保将必要的标志添加到测试编译和实际编译中。
“yourfile.c”看起来像这样:
#include <windows.h>
unsigned long long get_tick_count(void) {
#ifdef CONF_HASGETTICKCOUNT64
return GetTickCount64();
#else
return GetTickCount();
#endif
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4826 次 |
| 最近记录: |