|
| 1 | +// |
| 2 | +// SwiftBridging.h |
| 3 | +// OpenAttributeGraphCxx |
| 4 | +// |
| 5 | +// Cross-platform Swift bridging compatibility header to solve <swift/bridging> issue on non-Darwin swift toolchain |
| 6 | +// Based on WebKit's SwiftBridging.h approach https://github.com/WebKit/WebKit/blob/84fc0edf9e8649a56cca35cc48c73f211e310d14/Source/WTF/wtf/SwiftBridging.h |
| 7 | + |
| 8 | +#pragma once |
| 9 | + |
| 10 | +#if __has_include(<swift/bridging>) |
| 11 | + |
| 12 | +#include <swift/bridging> |
| 13 | + |
| 14 | +#ifndef SWIFT_NONESCAPABLE |
| 15 | +#define SWIFT_NONESCAPABLE |
| 16 | +#endif |
| 17 | + |
| 18 | +#ifndef SWIFT_ESCAPABLE |
| 19 | +#define SWIFT_ESCAPABLE |
| 20 | +#endif |
| 21 | + |
| 22 | +#ifndef SWIFT_RETURNS_UNRETAINED |
| 23 | +#define SWIFT_RETURNS_UNRETAINED |
| 24 | +#endif |
| 25 | + |
| 26 | +#ifndef SWIFT_ESCAPABLE_IF |
| 27 | +#define SWIFT_ESCAPABLE_IF(...) |
| 28 | +#endif |
| 29 | + |
| 30 | +#ifndef SWIFT_PRIVATE_FILEID |
| 31 | +#define SWIFT_PRIVATE_FILEID(_fileID) |
| 32 | +#endif |
| 33 | + |
| 34 | +#else |
| 35 | + |
| 36 | +// Copied from https://github.com/swiftlang/swift/blob/ff8b9f145320b02bc6de75163d78528f210bdba6/lib/ClangImporter/SwiftBridging/swift/bridging |
| 37 | + |
| 38 | +// -*- C++ -*- |
| 39 | +//===------------------ bridging - C++ and Swift Interop --------*- C++ -*-===// |
| 40 | +// |
| 41 | +// This source file is part of the Swift.org open source project |
| 42 | +// |
| 43 | +// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| 44 | +// Licensed under Apache License v2.0 with Runtime Library Exception |
| 45 | +// |
| 46 | +// See https://swift.org/LICENSE.txt for license information |
| 47 | +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| 48 | +// |
| 49 | +//===----------------------------------------------------------------------===// |
| 50 | +// |
| 51 | +// This file provides common utilities and annotations that are useful for C++ |
| 52 | +// codebases that interoperate with Swift. |
| 53 | +// |
| 54 | +//===----------------------------------------------------------------------===// |
| 55 | +#ifndef SWIFT_CLANGIMPORTER_SWIFT_INTEROP_SUPPORT_H |
| 56 | +#define SWIFT_CLANGIMPORTER_SWIFT_INTEROP_SUPPORT_H |
| 57 | + |
| 58 | +#ifdef __has_attribute |
| 59 | +#define _CXX_INTEROP_HAS_ATTRIBUTE(x) __has_attribute(x) |
| 60 | +#else |
| 61 | +#define _CXX_INTEROP_HAS_ATTRIBUTE(x) 0 |
| 62 | +#endif |
| 63 | + |
| 64 | +#if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr) |
| 65 | + |
| 66 | +/// Specifies that a C++ `class` or `struct` owns and controls the lifetime of all |
| 67 | +/// of the objects it references. Such type should not reference any objects whose |
| 68 | +/// lifetime is controlled externally. This annotation allows Swift to import methods |
| 69 | +/// that return a `class` or `struct` type that is annotated with this macro. |
| 70 | +#define SWIFT_SELF_CONTAINED __attribute__((swift_attr("import_owned"))) |
| 71 | + |
| 72 | +/// Specifies that a C++ method returns a value that is presumed to contain |
| 73 | +/// objects whose lifetime is not dependent on `this` or other parameters passed |
| 74 | +/// to the method. |
| 75 | +#define SWIFT_RETURNS_INDEPENDENT_VALUE __attribute__((swift_attr("import_unsafe"))) |
| 76 | + |
| 77 | +#define _CXX_INTEROP_STRINGIFY(_x) #_x |
| 78 | + |
| 79 | +#define _CXX_INTEROP_CONCAT_(a,b,c,d,e,f,g,i,j,k,l,m,n,o,p,...) \ |
| 80 | + #a "," #b "," #c "," #d "," #e "," #f "," #g "," #i "," #j "," #k "," \ |
| 81 | + #l "," #m "," #n "," #o "," #p |
| 82 | +#define _CXX_INTEROP_CONCAT(...) \ |
| 83 | + _CXX_INTEROP_CONCAT_(__VA_ARGS__,,,,,,,,,,,,,,,,,) |
| 84 | + |
| 85 | +/// Specifies that a C++ `class` or `struct` is reference-counted using |
| 86 | +/// the given `retain` and `release` functions. This annotation lets Swift import |
| 87 | +/// such a type as reference counted type in Swift, taking advantage of Swift's |
| 88 | +/// automatic reference counting. |
| 89 | +/// |
| 90 | +/// This example shows how to use this macro to let Swift know that |
| 91 | +/// a non-copyable reference counted C++ class can be imported as a reference counted type in Swift: |
| 92 | +/// ```c++ |
| 93 | +/// class SWIFT_SHARED_REFERENCE(retainSharedObject, releaseSharedObject) |
| 94 | +/// SharedObject : NonCopyable, IntrusiveReferenceCounted<SharedObject> { |
| 95 | +/// public: |
| 96 | +/// static SharedObject* create(); |
| 97 | +/// void doSomething(); |
| 98 | +/// }; |
| 99 | +/// |
| 100 | +/// void retainSharedObject(SharedObject *); |
| 101 | +/// void releaseSharedObject(SharedObject *); |
| 102 | +/// ``` |
| 103 | +/// |
| 104 | +/// Then, the Swift programmer would be able to use it in the following manner: |
| 105 | +/// |
| 106 | +/// ```swift |
| 107 | +/// let object = SharedObject.create() |
| 108 | +/// object.doSomething() |
| 109 | +/// // The Swift compiler will release object here. |
| 110 | +/// ``` |
| 111 | +#define SWIFT_SHARED_REFERENCE(_retain, _release) \ |
| 112 | + __attribute__((swift_attr("import_reference"))) \ |
| 113 | + __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(retain:_retain)))) \ |
| 114 | + __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(release:_release)))) |
| 115 | + |
| 116 | +/// Specifies that a C++ `class` or `struct` is a reference type whose lifetime |
| 117 | +/// is presumed to be immortal, i.e. the reference to such object is presumed to |
| 118 | +/// always be valid. This annotation lets Swift import such a type as a reference |
| 119 | +/// type in Swift. |
| 120 | +//// |
| 121 | +/// This example shows how to use this macro to let Swift know that |
| 122 | +/// a non-copyable singleton C++ class can be imported as a reference type in Swift: |
| 123 | +/// ```c++ |
| 124 | +/// class SWIFT_IMMORTAL_REFERENCE |
| 125 | +/// LoggerSingleton : NonCopyable { |
| 126 | +/// public: |
| 127 | +/// static LoggerSingleton &getInstance(); |
| 128 | +/// void log(int x); |
| 129 | +/// }; |
| 130 | +/// ``` |
| 131 | +/// |
| 132 | +/// Then, the Swift programmer would be able to use it in the following manner: |
| 133 | +/// |
| 134 | +/// ```swift |
| 135 | +/// let logger = LoggerSingleton.getInstance() |
| 136 | +/// logger.log(123) |
| 137 | +/// ``` |
| 138 | +#define SWIFT_IMMORTAL_REFERENCE \ |
| 139 | + __attribute__((swift_attr("import_reference"))) \ |
| 140 | + __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(retain:immortal)))) \ |
| 141 | + __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(release:immortal)))) |
| 142 | + |
| 143 | +/// Specifies that a C++ `class` or `struct` is a reference type whose lifetime |
| 144 | +/// is not managed automatically. The programmer must validate that any reference |
| 145 | +/// to such object is valid themselves. This annotation lets Swift import such a type as a reference type in Swift. |
| 146 | +#define SWIFT_UNSAFE_REFERENCE \ |
| 147 | + __attribute__((swift_attr("import_reference"))) \ |
| 148 | + __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(retain:immortal)))) \ |
| 149 | + __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(release:immortal)))) \ |
| 150 | + __attribute__((swift_attr("unsafe"))) |
| 151 | + |
| 152 | +/// Specifies a name that will be used in Swift for this declaration instead of its original name. |
| 153 | +#define SWIFT_NAME(_name) __attribute__((swift_name(#_name))) |
| 154 | + |
| 155 | +/// Specifies that a specific C++ `class` or `struct` conforms to a |
| 156 | +/// a specific Swift protocol. |
| 157 | +/// |
| 158 | +/// This example shows how to use this macro to conform a class template to a Swift protocol: |
| 159 | +/// ``` |
| 160 | +/// template<class T> |
| 161 | +/// class SWIFT_CONFORMS_TO_PROTOCOL(SwiftModule.ProtocolName) |
| 162 | +/// CustomClass {}; |
| 163 | +/// ``` |
| 164 | +#define SWIFT_CONFORMS_TO_PROTOCOL(_moduleName_protocolName) \ |
| 165 | + __attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(conforms_to:_moduleName_protocolName)))) |
| 166 | + |
| 167 | +/// Specifies that a specific C++ method should be imported as a computed |
| 168 | +/// property. If this macro is specified on a getter, a getter will be |
| 169 | +/// synthesized. If this macro is specified on a setter, both a getter and |
| 170 | +/// setter will be synthesized. |
| 171 | +/// |
| 172 | +/// For example: |
| 173 | +/// ``` |
| 174 | +/// int getX() SWIFT_COMPUTED_PROPERTY; |
| 175 | +/// ``` |
| 176 | +/// Will be imported as `var x: CInt {...}`. |
| 177 | +#define SWIFT_COMPUTED_PROPERTY \ |
| 178 | + __attribute__((swift_attr("import_computed_property"))) |
| 179 | + |
| 180 | +/// Specifies that a specific **constant** C++ member function should be imported as |
| 181 | +/// `mutating` Swift method. This annotation should be added to constant C++ member functions |
| 182 | +/// that mutate `mutable` fields in a C++ object, to let Swift know that this function is still mutating |
| 183 | +/// and thus that it should become a `mutating` method in Swift. |
| 184 | +#define SWIFT_MUTATING \ |
| 185 | + __attribute__((swift_attr("mutating"))) |
| 186 | + |
| 187 | +/// Specifies that a specific c++ type such class or struct should be imported as type marked |
| 188 | +/// as `@unchecked Sendable` type in swift. If this annotation is used, the type is therefore allowed to |
| 189 | +/// use safely across async contexts. |
| 190 | +/// |
| 191 | +/// For example |
| 192 | +/// ``` |
| 193 | +/// class SWIFT_UNCHECKED_SENDABLE CustomUserType |
| 194 | +/// { ... } |
| 195 | +/// ``` |
| 196 | +/// Will be imported as `struct CustomUserType: @unchecked Sendable` |
| 197 | +#define SWIFT_UNCHECKED_SENDABLE \ |
| 198 | + __attribute__((swift_attr("@Sendable"))) |
| 199 | + |
| 200 | +/// Specifies that a specific c++ type such class or struct should be imported |
| 201 | +/// as a non-copyable Swift value type. |
| 202 | +#define SWIFT_NONCOPYABLE \ |
| 203 | + __attribute__((swift_attr("~Copyable"))) |
| 204 | + |
| 205 | +/// Specifies that a specific c++ type such class or struct should be imported |
| 206 | +/// as a non-escapable Swift value type when the non-escapable language feature |
| 207 | +/// is enabled. |
| 208 | +#define SWIFT_NONESCAPABLE \ |
| 209 | + __attribute__((swift_attr("~Escapable"))) |
| 210 | + |
| 211 | +/// Specifies that a specific c++ type such class or struct should be imported |
| 212 | +/// as a escapable Swift value. While this matches the default behavior, |
| 213 | +/// in safe mode interop mode it ensures that the type is not marked as |
| 214 | +/// unsafe. |
| 215 | +#define SWIFT_ESCAPABLE \ |
| 216 | + __attribute__((swift_attr("Escapable"))) |
| 217 | + |
| 218 | +/// Specifies that a C++ `class` or `struct` should be imported as a escapable |
| 219 | +/// Swift value if all of the specified template arguments are escapable. |
| 220 | +#define SWIFT_ESCAPABLE_IF(...) \ |
| 221 | + __attribute__((swift_attr("escapable_if:" _CXX_INTEROP_CONCAT(__VA_ARGS__)))) |
| 222 | + |
| 223 | +/// Specifies that the return value is passed as owned for C++ functions and |
| 224 | +/// methods returning types annotated as `SWIFT_SHARED_REFERENCE` |
| 225 | +#define SWIFT_RETURNS_RETAINED __attribute__((swift_attr("returns_retained"))) |
| 226 | +/// Specifies that the return value is passed as unowned for C++ functions and |
| 227 | +/// methods returning types annotated as `SWIFT_SHARED_REFERENCE` |
| 228 | +#define SWIFT_RETURNS_UNRETAINED \ |
| 229 | + __attribute__((swift_attr("returns_unretained"))) |
| 230 | + |
| 231 | +/// Applied to a C++ foreign reference type annotated with |
| 232 | +/// SWIFT_SHARED_REFERENCE. Indicates that C++ APIs returning this type are |
| 233 | +/// assumed to return an unowned (+0) value by default, unless explicitly annotated |
| 234 | +/// with SWIFT_RETURNS_RETAINED. |
| 235 | +/// |
| 236 | +/// For example: |
| 237 | +/// ```c++ |
| 238 | +/// struct SWIFT_SHARED_REFERENCE(retainBar, releaseBar) |
| 239 | +/// SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT |
| 240 | +/// Bar { ... }; |
| 241 | +/// ``` |
| 242 | +/// |
| 243 | +/// In Swift, C++ APIs returning `Bar*` will be assumed to return an unowned |
| 244 | +/// value. |
| 245 | +#define SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT \ |
| 246 | + __attribute__((swift_attr("returned_as_unretained_by_default"))) |
| 247 | + |
| 248 | +/// Specifies that the non-public members of a C++ class, struct, or union can |
| 249 | +/// be accessed from extensions of that type, in the given file ID. |
| 250 | +/// |
| 251 | +/// In other words, Swift's access controls will behave as if the non-public |
| 252 | +/// members of the annotated C++ class were privated declared in the specified |
| 253 | +/// Swift source file, rather than in a C++ header file/Clang module. |
| 254 | +/// |
| 255 | +/// For example, we can annotate a C++ class definition like this: |
| 256 | +/// |
| 257 | +/// ```c++ |
| 258 | +/// class SWIFT_PRIVATE_FILEID("MySwiftModule/MySwiftFile.swift") |
| 259 | +/// MyCxxClass { |
| 260 | +/// private: |
| 261 | +/// void privateMethod(); |
| 262 | +/// int privateStorage; |
| 263 | +/// }; |
| 264 | +/// ``` |
| 265 | +/// |
| 266 | +/// Then, Swift extensions of `MyCxxClass` in `MySwiftModule/MySwiftFile.swift` |
| 267 | +/// are allowed to access `privateMethod()` and `privateStorage`: |
| 268 | +/// |
| 269 | +/// ```swift |
| 270 | +/// //-- MySwiftModule/SwiftFile.swift |
| 271 | +/// extension MyCxxClass { |
| 272 | +/// func ext() { |
| 273 | +/// privateMethod() |
| 274 | +/// print("\(privateStorage)") |
| 275 | +/// } |
| 276 | +/// } |
| 277 | +/// ``` |
| 278 | +/// |
| 279 | +/// Non-public access is still forbidden outside of extensions and outside of |
| 280 | +/// the designated file ID. |
| 281 | +#define SWIFT_PRIVATE_FILEID(_fileID) \ |
| 282 | + __attribute__((swift_attr("private_fileid:" _fileID))) |
| 283 | + |
| 284 | +#else // #if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr) |
| 285 | + |
| 286 | +// Empty defines for compilers that don't support `attribute(swift_attr)`. |
| 287 | +#define SWIFT_SELF_CONTAINED |
| 288 | +#define SWIFT_RETURNS_INDEPENDENT_VALUE |
| 289 | +#define SWIFT_SHARED_REFERENCE(_retain, _release) |
| 290 | +#define SWIFT_IMMORTAL_REFERENCE |
| 291 | +#define SWIFT_UNSAFE_REFERENCE |
| 292 | +#define SWIFT_NAME(_name) |
| 293 | +#define SWIFT_CONFORMS_TO_PROTOCOL(_moduleName_protocolName) |
| 294 | +#define SWIFT_COMPUTED_PROPERTY |
| 295 | +#define SWIFT_MUTATING |
| 296 | +#define SWIFT_UNCHECKED_SENDABLE |
| 297 | +#define SWIFT_NONCOPYABLE |
| 298 | +#define SWIFT_NONESCAPABLE |
| 299 | +#define SWIFT_ESCAPABLE |
| 300 | +#define SWIFT_ESCAPABLE_IF(...) |
| 301 | +#define SWIFT_RETURNS_RETAINED |
| 302 | +#define SWIFT_RETURNS_UNRETAINED |
| 303 | +#define SWIFT_PRIVATE_FILEID(_fileID) |
| 304 | + |
| 305 | +#endif // #if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr) |
| 306 | + |
| 307 | +#undef _CXX_INTEROP_HAS_ATTRIBUTE |
| 308 | + |
| 309 | +#endif // SWIFT_CLANGIMPORTER_SWIFT_INTEROP_SUPPORT_H |
| 310 | + |
| 311 | +#endif |
0 commit comments