c - Obj-C 有@available。 swift 有#available。我可以在 C/C++ 中使用什么?

标签 c objective-c swift macos

如果您的代码需要仅在 macOS 10.12 或更高版本中可用的功能,但您希望您的代码也部署到更早的系统版本,您可以使用 @available在 Objective-C 中:

if (@available(macOS 10.12, *)) {
    // Code that requires 10.12 APIs
} else {
    // Code that doesn't require 10.12 APIs
}
你可以在 Swift 中使用 #available 做同样的事情。 :
if #available(macOS 10.12, *) {
    // Code that requires 10.12 APIs
} else {
    // Code that doesn't require 10.12 APIs
}
但是,如果您编写 C 或 C++ 代码,您可以使用什么?

最佳答案

在 C 和 C++ 中,您可以使用 Clang 编译器扩展 __builtin_available :

if (__builtin_available(macOS 10.12, *)) {
    // Code that requires 10.12 APIs
} else {
    // Code that doesn't require 10.12 APIs
}
也就是说,如果您至少有 Clang 5 可用(Xcode 5.0 或更新版本)。
请记住,您必须设置部署目标才能使此功能正常工作(例如 -mmacosx-version-min=10.9 )。原因是链接器需要此信息来决定何时执行弱链接。例如,将部署目标设置为 10.9 会告诉链接器,如果您的代码使用了 10.9 中尚不可用的任何符号,则这些符号必须是弱链接的。
通常,可执行文件或库会在加载时尝试解析所有引用的符号,如果找不到任何此类符号,则无法加载。但是,当符号是弱链接时,无法解析符号不会导致加载失败,而是对该符号的任何引用都会变成 NULL运行时引用。不用说,如果您尝试调用一个弱链接且在加载时未找到的函数,您的应用程序将崩溃(您尝试将 NULL 作为函数调用)。这就是__builtin_available来救援。
if (__builtin_available(macOS 10.12, *)) {
    // ...
} else {
    // Symbols only available in 10.12 or newer are all NULL when
    // you reach this code block but you wouldn't use any of them
    // in this code block, would you? So, no problem.
}
如果您不使用 -mmacosx-version-min , __builtin_available构造仍然可以正常工作,但由于链接器不知道您的目标系统,它假定当前系统并且不会执行任何弱链接。如果您随后尝试在较早的系统版本上运行您的应用程序,则将找不到某些符号,并且您的应用程序甚至拒绝加载,尽管它具有该系统的替代代码路径。

关于c - Obj-C 有@available。 swift 有#available。我可以在 C/C++ 中使用什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57825757/

相关文章:

objective-c - NSUndoManager 不会撤消 NSMutableDictionary 的编辑

objective-c - 在 Yosemite 上与 Frank 进行的 cucumber 测试导致段错误

ios - 用于错误处理的 swift 中的 Guard 语句

无法将 int 打印到文件

c - 警告 : implicit declaration of function ' crypt_r'

c - C根据字符串路径判断文件是否存在

arrays - Swift 扩展 UInt8 数组

c - C 字节读取器中的段错误(核心转储)

iphone - cocos2d 中的自由运行/横向滚动类型游戏

objective-c - 替换 nsmutablearray 中的对象