<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="" applecontenteditable="true"><br class=""><div><blockquote type="cite" class=""><div class="">On Apr 3, 2017, at 09:04, Joe Groff via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On Apr 1, 2017, at 6:48 AM, Jean-Daniel &lt;<a href="mailto:mailing@xenonium.com" class="">mailing@xenonium.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">Le 1 avr. 2017 à 00:53, Joe Groff via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; a écrit :</div><br class="Apple-interchange-newline"><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="Apple-interchange-newline">On Mar 31, 2017, at 8:00 AM, Charles Srstka via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class="">MOTIVATION:<br class=""><br class="">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:<br class=""><br class="">GeneratePreview.swift:<br class=""><br class="">class QLGlue: NSObject {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>@objc static func generatePreview(_: UnsafeMutableRawPointer, request preview: QLPreviewRequest, url: URL, contentTypeUTI: String, options: [String : Any]) -&gt; OSStatus {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// generate the preview<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class="">}<br class=""><br class="">GeneratePreview.m:<br class=""><br class="">#import “MyProject-Swift.h"<br class=""><br class="">OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef request, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options) {<br class="">&nbsp;&nbsp;return [QLGlue generatePreview:thisInterface request:request url:(__bridge NSURL *)url contentTypeUTI:(__bridge NSString *)contentTypeUTI options:(__bridge NSDictionary *)options];<br class="">}<br class=""><br class="">PROPOSED SOLUTION:<br class=""><br class="">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:<br class=""><br class="">@objc func generatePreview(_: UnsafeMutableRawPointer, _ preview: QLPreviewRequest, _ url: CFURL, _ contentTypeUTI: CFString, _ options: CFDictionary) -&gt; OSStatus {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// generate the preview<br class="">}<br class=""><br class="">This would eliminate an entire source file of glue code.<br class=""><br class="">IMPACT ON EXISTING CODE:<br class=""><br class="">None, since @objc is not currently allowed on top-level functions. This is purely additive.<br class=""></blockquote><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">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.</span><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">-Joe</span><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"></div></blockquote><div class=""><br class=""></div></div><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">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.</span><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Maybe it is enough to say that ‘internal' symbols should be exported as «&nbsp;private extern&nbsp;» and ‘public' symbol should be exported a «&nbsp;global&nbsp;», but I think it is worse mentioning it in a formal proposal.</div></div></blockquote></div><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">It seems to me like the symbol visibility ought to follow the same rules as for Swift symbols.</div></div></blockquote><br class=""></div><div>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.</div><div><br class=""></div><div>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.</div><div><br class=""></div><div>Jordan</div><br class=""></body></html>