> On Apr 3, 2017, at 09:04, Joe Groff via swift-evolution > <[email protected]> wrote: > >> >> On Apr 1, 2017, at 6:48 AM, Jean-Daniel <[email protected] >> <mailto:[email protected]>> wrote: >> >>> >>> Le 1 avr. 2017 à 00:53, Joe Groff via swift-evolution >>> <[email protected] <mailto:[email protected]>> a écrit : >>> >>>> >>>> On Mar 31, 2017, at 8:00 AM, Charles Srstka via swift-evolution >>>> <[email protected] <mailto:[email protected]>> wrote: >>>> >>>> MOTIVATION: >>>> >>>> Sometimes, it’s necessary to write a top-level C function in order to >>>> interact with some C-based code. This can come up, for example, when >>>> making a new port for a cross-platform app that implements OS-dependent >>>> functionality via C functions. More urgently, though, it also pops up in >>>> certain Apple APIs, such as the standard QuickLook plug-in template. In >>>> order to write a QuickLook plug-in, developers are required to write >>>> implementations for certain predefined C functions, such as >>>> GeneratePreviewForURL(), GenerateThumbnailForURL(), >>>> CancelPreviewGeneration(), and CancelThumbnailGeneration(). Unfortunately, >>>> this API contract cannot be met in Swift. Currently, Swift can only expose >>>> class members to C/Objective-C, which means that implementing a QuickLook >>>> plug-in involves a rather awkward series of hoops to jump through: >>>> >>>> GeneratePreview.swift: >>>> >>>> class QLGlue: NSObject { >>>> @objc static func generatePreview(_: UnsafeMutableRawPointer, request >>>> preview: QLPreviewRequest, url: URL, contentTypeUTI: String, options: >>>> [String : Any]) -> OSStatus { >>>> // generate the preview >>>> } >>>> } >>>> >>>> GeneratePreview.m: >>>> >>>> #import “MyProject-Swift.h" >>>> >>>> OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef >>>> request, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef >>>> options) { >>>> return [QLGlue generatePreview:thisInterface request:request >>>> url:(__bridge NSURL *)url contentTypeUTI:(__bridge NSString >>>> *)contentTypeUTI options:(__bridge NSDictionary *)options]; >>>> } >>>> >>>> PROPOSED SOLUTION: >>>> >>>> Allow the @objc on top-level functions. This will cause the functions to >>>> be exposed as C functions, satisfying contracts such as Apple’s QuickLook >>>> plug-in contract, and allowing developers to just write: >>>> >>>> @objc func generatePreview(_: UnsafeMutableRawPointer, _ preview: >>>> QLPreviewRequest, _ url: CFURL, _ contentTypeUTI: CFString, _ options: >>>> CFDictionary) -> OSStatus { >>>> // generate the preview >>>> } >>>> >>>> This would eliminate an entire source file of glue code. >>>> >>>> IMPACT ON EXISTING CODE: >>>> >>>> None, since @objc is not currently allowed on top-level functions. This is >>>> purely additive. >>> >>> This would definitely be useful, even beyond ObjC interop. There is in fact >>> an unfinished implementation of a `@_cdecl("symbolName")` attribute that >>> you can use to export a global function as a C-compatible symbol. What's >>> missing (IIRC) is bridging header support to expose the declaration back to >>> C, compiler checking for symbol name collisions, and decoupling the >>> validation from ObjC interop for non-Apple platforms—and, of course, a >>> formal evolution proposal to make it an official part of the language. I >>> don't think we want to call this @objc, since it isn't inherently tied to >>> ObjC, and IMO it makes sense to require the exported symbol name to be >>> required, since top-level unmangled symbols are a crowded namespace, and it >>> would be good to ensure people think about the C symbol name they export. >>> >>> -Joe >> >> We should also think about a way to specify the symbol visibility. It may be >> useful to export a global function to interact with C code, but that don’t >> mean we want to export it and make it visible outside of the module. >> Maybe it is enough to say that ‘internal' symbols should be exported as « >> private extern » and ‘public' symbol should be exported a « global », but I >> think it is worse mentioning it in a formal proposal. > > It seems to me like the symbol visibility ought to follow the same rules as > for Swift symbols.
Note that we don't have a good way to do this with a single generated header. But we could just limit printing to public symbols, and force people to redeclare the signature on the C side otherwise for now. Also missing: proper validation of what can be exposed to C on a platform without ObjC or bridging. We have a lot of tests for what is and isn't valid @objc, but very few for C, and there will be divergence in some places. Jordan
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
