mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
298 lines
12 KiB
Plaintext
298 lines
12 KiB
Plaintext
// -*- C -*-
|
|
//===------------------ bridging - C and Swift Interop ----------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file provides common utilities and annotations that are useful for C++
|
|
// codebases that interoperate with Swift.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#ifndef SWIFT_CLANGIMPORTER_SWIFT_INTEROP_SUPPORT_H
|
|
#define SWIFT_CLANGIMPORTER_SWIFT_INTEROP_SUPPORT_H
|
|
|
|
#ifdef __has_attribute
|
|
#define _CXX_INTEROP_HAS_ATTRIBUTE(x) __has_attribute(x)
|
|
#else
|
|
#define _CXX_INTEROP_HAS_ATTRIBUTE(x) 0
|
|
#endif
|
|
|
|
#if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr)
|
|
|
|
/// Specifies that a C++ `class` or `struct` owns and controls the lifetime of all
|
|
/// of the objects it references. Such type should not reference any objects whose
|
|
/// lifetime is controlled externally. This annotation allows Swift to import methods
|
|
/// that return a `class` or `struct` type that is annotated with this macro.
|
|
#define SWIFT_SELF_CONTAINED __attribute__((swift_attr("import_owned")))
|
|
|
|
/// Specifies that a method returns a value that is presumed to contain
|
|
/// objects whose lifetime is not dependent on `this` or other parameters passed
|
|
/// to the method.
|
|
#define SWIFT_RETURNS_INDEPENDENT_VALUE __attribute__((swift_attr("import_unsafe")))
|
|
|
|
#define _CXX_INTEROP_STRINGIFY(_x) #_x
|
|
|
|
#define _CXX_INTEROP_CONCAT_(a,b,c,d,e,f,g,i,j,k,l,m,n,o,p,...) \
|
|
#a "," #b "," #c "," #d "," #e "," #f "," #g "," #i "," #j "," #k "," \
|
|
#l "," #m "," #n "," #o "," #p
|
|
#define _CXX_INTEROP_CONCAT(...) \
|
|
_CXX_INTEROP_CONCAT_(__VA_ARGS__,,,,,,,,,,,,,,,,,)
|
|
|
|
/// Specifies that a `class` or `struct` is reference-counted using
|
|
/// the given `retain` and `release` functions. This annotation lets Swift import
|
|
/// such a type as reference counted type in Swift, taking advantage of Swift's
|
|
/// automatic reference counting.
|
|
///
|
|
/// This example shows how to use this macro to let Swift know that
|
|
/// a non-copyable reference counted C++ class can be imported as a reference counted type in Swift:
|
|
/// ```c++
|
|
/// class SWIFT_SHARED_REFERENCE(retainSharedObject, releaseSharedObject)
|
|
/// SharedObject : NonCopyable, IntrusiveReferenceCounted<SharedObject> {
|
|
/// public:
|
|
/// static SharedObject* create();
|
|
/// void doSomething();
|
|
/// };
|
|
///
|
|
/// void retainSharedObject(SharedObject *);
|
|
/// void releaseSharedObject(SharedObject *);
|
|
/// ```
|
|
///
|
|
/// Then, the Swift programmer would be able to use it in the following manner:
|
|
///
|
|
/// ```swift
|
|
/// let object = SharedObject.create()
|
|
/// object.doSomething()
|
|
/// // The Swift compiler will release object here.
|
|
/// ```
|
|
#define SWIFT_SHARED_REFERENCE(_retain, _release) \
|
|
__attribute__((swift_attr("import_reference"))) \
|
|
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(retain:_retain)))) \
|
|
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(release:_release))))
|
|
|
|
/// Specifies that a `class` or `struct` is a reference type whose lifetime
|
|
/// is presumed to be immortal, i.e. the reference to such object is presumed to
|
|
/// always be valid. This annotation lets Swift import such a type as a reference
|
|
/// type in Swift.
|
|
////
|
|
/// This example shows how to use this macro to let Swift know that
|
|
/// a non-copyable singleton C++ class can be imported as a reference type in Swift:
|
|
/// ```c++
|
|
/// class SWIFT_IMMORTAL_REFERENCE
|
|
/// LoggerSingleton : NonCopyable {
|
|
/// public:
|
|
/// static LoggerSingleton &getInstance();
|
|
/// void log(int x);
|
|
/// };
|
|
/// ```
|
|
///
|
|
/// Then, the Swift programmer would be able to use it in the following manner:
|
|
///
|
|
/// ```swift
|
|
/// let logger = LoggerSingleton.getInstance()
|
|
/// logger.log(123)
|
|
/// ```
|
|
#define SWIFT_IMMORTAL_REFERENCE \
|
|
__attribute__((swift_attr("import_reference"))) \
|
|
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(retain:immortal)))) \
|
|
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(release:immortal))))
|
|
|
|
/// Specifies that a `class` or `struct` is a reference type whose lifetime
|
|
/// is not managed automatically. The programmer must validate that any reference
|
|
/// to such object is valid themselves. This annotation lets Swift import such a type as a reference type in Swift.
|
|
#define SWIFT_UNSAFE_REFERENCE \
|
|
__attribute__((swift_attr("import_reference"))) \
|
|
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(retain:immortal)))) \
|
|
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(release:immortal)))) \
|
|
__attribute__((swift_attr("unsafe")))
|
|
|
|
/// Specifies a name that will be used in Swift for this declaration instead of its original name.
|
|
#define SWIFT_NAME(_name) __attribute__((swift_name(#_name)))
|
|
|
|
/// Specifies that a specific `class` or `struct` conforms to a
|
|
/// a specific Swift protocol.
|
|
///
|
|
/// This example shows how to use this macro to conform a class template to a Swift protocol:
|
|
/// ```
|
|
/// template<class T>
|
|
/// class SWIFT_CONFORMS_TO_PROTOCOL(SwiftModule.ProtocolName)
|
|
/// CustomClass {};
|
|
/// ```
|
|
#define SWIFT_CONFORMS_TO_PROTOCOL(_moduleName_protocolName) \
|
|
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(conforms_to:_moduleName_protocolName))))
|
|
|
|
/// Specifies that a specific C++ method should be imported as a computed
|
|
/// property. If this macro is specified on a getter, a getter will be
|
|
/// synthesized. If this macro is specified on a setter, both a getter and
|
|
/// setter will be synthesized.
|
|
///
|
|
/// For example:
|
|
/// ```
|
|
/// int getX() SWIFT_COMPUTED_PROPERTY;
|
|
/// ```
|
|
/// Will be imported as `var x: CInt {...}`.
|
|
#define SWIFT_COMPUTED_PROPERTY \
|
|
__attribute__((swift_attr("import_computed_property")))
|
|
|
|
/// Specifies that a specific **constant** C++ member function should be imported as
|
|
/// `mutating` Swift method. This annotation should be added to constant C++ member functions
|
|
/// that mutate `mutable` fields in a C++ object, to let Swift know that this function is still mutating
|
|
/// and thus that it should become a `mutating` method in Swift.
|
|
#define SWIFT_MUTATING \
|
|
__attribute__((swift_attr("mutating")))
|
|
|
|
/// Specifies that a specific class or struct should be imported as type marked
|
|
/// as `@unchecked Sendable` type in swift. If this annotation is used, the type is therefore allowed to
|
|
/// use safely across async contexts.
|
|
///
|
|
/// For example
|
|
/// ```
|
|
/// class SWIFT_UNCHECKED_SENDABLE CustomUserType
|
|
/// { ... }
|
|
/// ```
|
|
/// Will be imported as `struct CustomUserType: @unchecked Sendable`
|
|
#define SWIFT_UNCHECKED_SENDABLE \
|
|
__attribute__((swift_attr("@Sendable")))
|
|
|
|
/// Specifies that a `class` or `struct` should be imported as a non-copyable
|
|
/// Swift value type.
|
|
#define SWIFT_NONCOPYABLE \
|
|
__attribute__((swift_attr("~Copyable")))
|
|
|
|
/// Specifies that a `class` or `struct` should be imported as a non-copyable
|
|
/// Swift value type that calls the given `_destroy` function when a value is no
|
|
/// longer used.
|
|
///
|
|
/// This example shows how to use this macro to let Swift know that
|
|
/// a given C struct should have its members freed when it goes out of scope:
|
|
/// ```c
|
|
/// typedef struct SWIFT_NONCOPYABLE_WITH_DESTROY(mytypeFreeMembers) MyType {
|
|
/// void *storage
|
|
/// } MyType;
|
|
///
|
|
/// void mytypeFreeMembers(MyType toBeDestroyed);
|
|
/// MyType mytypeCreate(void);
|
|
/// ```
|
|
///
|
|
/// Usage in Swift:
|
|
/// ```swift
|
|
/// let mt = mytypeCreate()
|
|
/// let mt2 = mt // consumes mt
|
|
/// // once mt2 is unused, Swift will call mytypeFreeMembers(mt2)
|
|
/// ```
|
|
#define SWIFT_NONCOPYABLE_WITH_DESTROY(_destroy) \
|
|
__attribute__((swift_attr("~Copyable"))) \
|
|
__attribute__((swift_attr(_CXX_INTEROP_STRINGIFY(destroy:_destroy))))
|
|
|
|
/// Specifies that a specific class or struct should be imported
|
|
/// as a non-escapable Swift value type.
|
|
#define SWIFT_NONESCAPABLE \
|
|
__attribute__((swift_attr("~Escapable")))
|
|
|
|
/// Specifies that a specific class or struct should be imported
|
|
/// as an escapable Swift value. While this matches the default behavior,
|
|
/// in safe mode interop mode it ensures that the type is not marked as
|
|
/// unsafe.
|
|
#define SWIFT_ESCAPABLE \
|
|
__attribute__((swift_attr("Escapable")))
|
|
|
|
/// Specifies that a C++ `class` or `struct` should be imported as a escapable
|
|
/// Swift value if all of the specified template arguments are escapable.
|
|
#define SWIFT_ESCAPABLE_IF(...) \
|
|
__attribute__((swift_attr("escapable_if:" _CXX_INTEROP_CONCAT(__VA_ARGS__))))
|
|
|
|
/// Specifies that the return value is passed as owned for functions and
|
|
/// methods returning types annotated as `SWIFT_SHARED_REFERENCE`
|
|
#define SWIFT_RETURNS_RETAINED __attribute__((swift_attr("returns_retained")))
|
|
/// Specifies that the return value is passed as unowned for functions and
|
|
/// methods returning types annotated as `SWIFT_SHARED_REFERENCE`
|
|
#define SWIFT_RETURNS_UNRETAINED \
|
|
__attribute__((swift_attr("returns_unretained")))
|
|
|
|
/// Applied to a foreign reference type annotated with
|
|
/// SWIFT_SHARED_REFERENCE. Indicates that APIs returning this type are
|
|
/// assumed to return an unowned (+0) value by default, unless explicitly annotated
|
|
/// with SWIFT_RETURNS_RETAINED.
|
|
///
|
|
/// For example:
|
|
/// ```c++
|
|
/// struct SWIFT_SHARED_REFERENCE(retainBar, releaseBar)
|
|
/// SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT
|
|
/// Bar { ... };
|
|
/// ```
|
|
///
|
|
/// In Swift, APIs returning `Bar*` will be assumed to return an unowned
|
|
/// value.
|
|
#define SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT \
|
|
__attribute__((swift_attr("returned_as_unretained_by_default")))
|
|
|
|
/// Specifies that the non-public members of a C++ class, struct, or union can
|
|
/// be accessed from extensions of that type, in the given file ID.
|
|
///
|
|
/// In other words, Swift's access controls will behave as if the non-public
|
|
/// members of the annotated C++ class were privated declared in the specified
|
|
/// Swift source file, rather than in a C++ header file/Clang module.
|
|
///
|
|
/// For example, we can annotate a C++ class definition like this:
|
|
///
|
|
/// ```c++
|
|
/// class SWIFT_PRIVATE_FILEID("MySwiftModule/MySwiftFile.swift")
|
|
/// MyCxxClass {
|
|
/// private:
|
|
/// void privateMethod();
|
|
/// int privateStorage;
|
|
/// };
|
|
/// ```
|
|
///
|
|
/// Then, Swift extensions of `MyCxxClass` in `MySwiftModule/MySwiftFile.swift`
|
|
/// are allowed to access `privateMethod()` and `privateStorage`:
|
|
///
|
|
/// ```swift
|
|
/// //-- MySwiftModule/SwiftFile.swift
|
|
/// extension MyCxxClass {
|
|
/// func ext() {
|
|
/// privateMethod()
|
|
/// print("\(privateStorage)")
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// Non-public access is still forbidden outside of extensions and outside of
|
|
/// the designated file ID.
|
|
#define SWIFT_PRIVATE_FILEID(_fileID) \
|
|
__attribute__((swift_attr("private_fileid:" _fileID)))
|
|
|
|
#else // #if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr)
|
|
|
|
// Empty defines for compilers that don't support `attribute(swift_attr)`.
|
|
#define SWIFT_SELF_CONTAINED
|
|
#define SWIFT_RETURNS_INDEPENDENT_VALUE
|
|
#define SWIFT_SHARED_REFERENCE(_retain, _release)
|
|
#define SWIFT_IMMORTAL_REFERENCE
|
|
#define SWIFT_UNSAFE_REFERENCE
|
|
#define SWIFT_NAME(_name)
|
|
#define SWIFT_CONFORMS_TO_PROTOCOL(_moduleName_protocolName)
|
|
#define SWIFT_COMPUTED_PROPERTY
|
|
#define SWIFT_MUTATING
|
|
#define SWIFT_UNCHECKED_SENDABLE
|
|
#define SWIFT_NONCOPYABLE
|
|
#define SWIDT_NONCOPYABLE_WITH_DESTROY(_destroy)
|
|
#define SWIFT_NONESCAPABLE
|
|
#define SWIFT_ESCAPABLE
|
|
#define SWIFT_ESCAPABLE_IF(...)
|
|
#define SWIFT_RETURNS_RETAINED
|
|
#define SWIFT_RETURNS_UNRETAINED
|
|
#define SWIFT_PRIVATE_FILEID(_fileID)
|
|
|
|
#endif // #if _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr)
|
|
|
|
#undef _CXX_INTEROP_HAS_ATTRIBUTE
|
|
|
|
#endif // SWIFT_CLANGIMPORTER_SWIFT_INTEROP_SUPPORT_H
|