为什么在OSX 10.8下编译时,下面的代码没有链接?我怎样才能将它链接起来以便它可以在10.8和10.9之间工作?我正在使用clang ++ 5.1。
// MyFile.cc
// Compile with: clang++ MyFile.cc -framework ApplicationServices
#include <ApplicationServices/ApplicationServices.h>
#include <iostream>
extern "C" CFStringRef kAXTrustedCheckOptionPrompt __attribute__ ((weak_import));
extern "C" Boolean AXIsProcessTrustedWithOptions (CFDictionaryRef options) __attribute__ ((weak_import));
static bool IsSupported (void)
{
return AXIsProcessTrustedWithOptions ?
AXIsProcessTrustedWithOptions (NULL):
AXAPIEnabled() || AXIsProcessTrusted();
}
int main (void)
{
std::cout << (IsSupported() ? "SUPPORTED\n" : "NOT SUPPORTED\n");
return 0;
}
注意:一切都在10.9中运行,二进制在10.8中运行。
答案 0 :(得分:1)
弱链接仍然需要链接。您链接的库或框架仍然必须定义符号。在10.8 SDK中,ApplicationServices框架没有定义AXIsProcessTrustedWithOptions
符号。
我至少可以想到这个符号必须由库定义的两个原因。首先,检测错误,例如代码中的符号名称是否有拼写错误。您希望链接器能够通知您该符号永远不可用。第二个(可能更重要),因为链接器和动态加载器的两级命名空间功能。对于动态库或框架提供的符号,链接器不仅记录符号名称,还记录解析它的库或框架。在加载时,符号与两者匹配。这允许两个动态库提供相同的符号,而不存在冲突或不正确绑定的风险。
如果您要针对10.8 SDK构建并仍然有条件地使用AXIsProcessTrustedWithOptions()
,则需要使用动态加载。您可以使用dlopen()
打开/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices,然后使用dlsym()
获取指向该函数的指针。检查指针是否为NULL
,将其转换为正确的类型,然后您可以调用它指向的函数。
static bool IsSupported (void)
{
static Boolean (*pAXIsProcessTrustedWithOptions)(CFDictionaryRef options);
static dispatch_once_t once;
dispatch_once(&once, ^{
void* handle = dlopen("/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices", 0);
if (handle)
pAXIsProcessTrustedWithOptions = dlsym(handle, "AXIsProcessTrustedWithOptions");
};
return pAXIsProcessTrustedWithOptions ?
pAXIsProcessTrustedWithOptions (NULL):
AXAPIEnabled() || AXIsProcessTrusted();
}