[swift-evolution] Pitch: @objc attribute for top-level functions

Jean-Daniel mailing at xenonium.com
Sat Apr 1 08:48:05 CDT 2017


> Le 1 avr. 2017 à 00:53, Joe Groff via swift-evolution <swift-evolution at swift.org> a écrit :
> 
>> 
>> On Mar 31, 2017, at 8:00 AM, Charles Srstka via swift-evolution <swift-evolution at swift.org> 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.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170401/9fbc19d5/attachment.html>


More information about the swift-evolution mailing list