Okay, why @objc @cdecl
together? When thinking this through, I considered several options:
-
@cdecl
and@objc
are both valid on top-level functions, but behave differently:@objc
allows using ObjC-only types and@cdecl
does not.- Upside: better checking of accidental reliance on ObjC interop.
- Downside: easy to use the wrong one, in theory.
- Downside: we may eventually want to allow
@cdecl
on member functions as well, the same way we have import-as-member for C functions, but@objc
already means something there.
-
@cdecl
and@objc
are interchangeable on Apple platforms, i.e. you can use ObjC-only types in@cdecl
functions.- Downside: accidental reliance on ObjC interop
- Downside: same thing about member functions
-
@cdecl
allows using ObjC-only types on Apple platforms and you can't write@objc
on a top-level function at all- Downside: accidental reliance on ObjC interop
-
@cdecl
does not allow ObjC-only types, and you can't write@objc
on a top-level function at all- Downside: seems like an artificial limitation - what if you want a top-level C-style function that takes an NSString? Or a CF type?
- This is my second choice, though, and it's easy to expand it to my original proposal later.
-
@cdecl
does not allow ObjC-only types, but@objc @cdecl
does- Downside: verbose and a little weird-looking
- Upside: better checking of accidental reliance on ObjC interop
- Easy to have the compiler help you if you need both but only have one
- This is my preferred option.
I also thought about increasing interop capabilities so that anything that Swift can expose to Objective-C can be exposed to C as well with some sort of opaque struct pointer type—then there are no more types requiring ObjC interop! Sadly, I came to the conclusion that it was just a dream, because you'd still expose them differently on platforms with/without ObjC interop, and it's unclear whether you'd even be able to tell what to expose from Swift when there's no such thing as "ObjC ancestry". (And you can't expose everything because Swift allows naming conflicts that C does not, thanks to modules and nesting. Additionally, exposing more things than @objc
does today would change the behavior of the "infer-@objc
-for-me" annotation @objcMembers
, which makes it a source-breaking change.)