Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Obj-C has @available. Swift has #available. What can I use in C/C++?

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
}

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

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

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

like image 230
Mecki Avatar asked Sep 06 '19 16:09

Mecki


People also ask

Is Objective-C compatible with Swift?

You can use Objective-C and Swift files together in a single project, no matter which language the project used originally. This makes creating mixed-language app and framework targets as straightforward as creating an app or framework target written in a single language.

How different is Objective-C from Swift?

Swift is a general-purpose, high-level programming language which is highly concerned about safety, performance. Objective C is an general purpose language which is considered as superset of C language it was designed in an aim of providing object-oriented capabilities.

Which is best Objective-C or Swift?

Swift has better memory management features than Objective-C, which can help improve performance. It uses lazy initialization, reducing memory usage since unused variables do not initialize—making it faster, easier to read and write, and safer.

What is advantage of Objective-C over Swift?

C++ compatibility It is incredibly easy to implement C++ code into an Obj-C project, which is one of the major advantages of Objective C over Swift. Considering the great number of programmers working with C++, this level of compatibility makes the language very appealing to a large audience.


1 Answers

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

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

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

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.

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 (you are trying to call NULL as a function). And that's where __builtin_available comes to the rescue.

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.
}

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 system.

like image 63
Mecki Avatar answered Nov 14 '22 21:11

Mecki