Obj-C有@available. Swift有#available.我可以在C/C ++中使用什么? [英] Obj-C has @available. Swift has #available. What can I use in C/C++?

查看:356
本文介绍了Obj-C有@available. Swift有#available.我可以在C/C ++中使用什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

If your code requires a feature that is only available in macOS 10.12 or newer, but you want your code to also deploy to earlier system versions, you can use @available in Objective-C:

if (@available(macOS 10.12, *)) {
    // Code that requires 10.12 APIs
} else {
    // Code that doesn't require 10.12 APIs
}

您可以使用#available在Swift中执行相同的操作:

You can do the same thing in Swift using #available:

if #available(OSX 10.12, *) {
    // Code that requires 10.12 APIs
} else {
    // Code that doesn't require 10.12 APIs
}

但是如果编写C或C ++代码,可以使用什么呢?

But what can you use if you write C or C++ code?

推荐答案

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

In C and C++ you can use the Clang compiler extension __builtin_available:

if (__builtin_available(OSX 10.12, *)) {
    // Code that requires 10.12 APIs
} else {
    // Code that doesn't require 10.12 APIs
}

也就是说,如果您至少有Clang 5可用(Xcode 5.0或更高版本).

That is if you have at least Clang 5 available (Xcode 5.0 or newer).

请记住,您必须设置一个部署目标才能使此功能正常运行(例如-mmacosx-version-min=10.9).原因是链接器需要此信息来决定何时执行弱链接.例如,将部署目标设置为10.9会告诉链接器,如果您的代码使用的是10.9中尚不可用的任何符号,则这些符号必须进行弱链接.

Keep in mind that you will have to set a deployment target to make this feature work correctly (e.g. -mmacosx-version-min=10.9). The reason is that the linker requires this information to decide when to perform weak linking. Setting the deployment target to 10.9 for example tells the linker that if your code is using any symbols that were not already available in 10.9, these symbols must be weakly linked.

通常,可执行文件或库将尝试在加载时解析所有引用的符号,如果找不到任何此类符号,则加载失败.但是,当符号被弱链接时,无法解析符号将不会导致加载失败,而是对该符号的任何引用在运行时都会成为NULL引用.不用说,如果您尝试调用一个链接较弱且未在加载时找到的函数,则您的应用程序将崩溃.这就是__builtin_available进行救援的地方.

Normally an executable or library will try to resolve all referenced symbols at load and fail to load if any such symbol cannot be found. However, when a symbol is weakly linked, being unable to resolve a symbol will not cause loading to fail, instead any reference to that symbol becomes a NULL reference at runtime. Needless to say, if you try to call a function that was weakly linked and has not been found at load, your app will crash. And that's where __builtin_available comes to the rescue.

if (__builtin_available(OSX 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构造仍将正常工作,但是由于链接器不知道您要定位的系统,因此它将假定当前系统并且不会执行任何弱链接.如果您随后尝试在较早的系统版本上运行您的应用程序,即使该版本具有该版本的替代代码路径,也不会找到一些符号,甚至拒绝加载您的应用程序.

If you don't use -mmacosx-version-min, the __builtin_available construct will still work correctly, yet as the linker doesn't know what system you are targeting, it assumes the current system and won't perform any weak linking. If you then try to run your app on an earlier system version, some symbols won't be found and your app even refuses to load, despite the fact that it would have alternative code paths for that version.

这篇关于Obj-C有@available. Swift有#available.我可以在C/C ++中使用什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆