2

Consider a private CFLocaleKey that is later bridged as an NSLocaleKey (NSString) for use internally with NSLocale:

CF_EXPORT const CFLocaleKey kCFLocaleTemperatureUnit API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

CFLocale_Private.h

The most obvious way to reference something like this would be through a bridging header. But is there a way to reference this CF/NSLocaleKey with pure Swift using something like @_silgen_name?

First I tried:

@_silgen_name("NSLocaleTemperatureUnit")
public let temperatureUnit: NSLocale.Key

But the compiler complains:

@_silgen_name cannot be applied to this declaration

Ok, let's make it static, but static properties can only be declared on a type. So I tried setting it up in the way the other NSLocaleKey values are bridged to Swift, as an extension on NSLocale.Key:

extension NSLocale.Key {
    @_silgen_name("NSLocaleTemperatureUnit")
    public static let temperatureUnit: NSLocale.Key
}

Even with this, the compiler complains with the same error as above. This is where I got stuck. Does @_silgen_name only work for functions? Is what I'm asking even possible with pure Swift?

JAL
  • 41,701
  • 23
  • 172
  • 300
  • I believe `@_silgen_name` is only an attribute to decorate functions, I have never seen it used for a type. – dfrib Aug 04 '17 at 17:47
  • @dfri I've only seen it on functions as well, I've been looking through the Swift open source repo. Any alternatives (or ideas) for "externing" a type in pure Swift? – JAL Aug 04 '17 at 17:48
  • Based on the quotes from Russ Bishop [in this related answer of mine](https://stackoverflow.com/a/35035099/4573247), I don't believe `@_silgen_name` can help you out in this case. As for alternatives or ideas, at the top of my name: no, not really, sorry :/ – dfrib Aug 04 '17 at 17:57
  • 1
    This might not be applicable in your case, but looking at [the comments in SR-5246 JIRA ticket](https://bugs.swift.org/browse/SR-5246), possible [the following approach from `NSSwiftRuntime.swift`](https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSSwiftRuntime.swift#L83) (using the `@_cdecl` attribute and casts of types to `UnsafeRawPointer`) could possible shed at least some insight on your problem. – dfrib Aug 04 '17 at 18:32
  • 1
    We're definitely getting closer, but `@_cdecl` may only be used on 'func' declarations. Thanks for a step in the right direction! – JAL Aug 04 '17 at 19:02
  • 1
    @dfri looks like we have our answer: https://twitter.com/JALsnipe/status/894200528003051521 – JAL Aug 08 '17 at 14:08
  • 1
    Good to get an answer directly from someone from the Swift compiler dev. team, even if it maybe wasn't the one your were looking for. Interesting Q&A nonetheless! – dfrib Aug 09 '17 at 06:30

1 Answers1

1

As of writing (August 8th, 2017), this currently is not possible with any version of Swift (3 or 4).

Without a header declaration, clang isn't sure how to map something in Swift back to C. @_silgen_name and @_cdecl work on functions, but not for variables.

This was confirmed by Jordan Rose, a Swift compiler engineer at Apple on Twitter.

tl;dr:

anything but func is hard.

JAL
  • 41,701
  • 23
  • 172
  • 300