> 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

Reply via email to