1
1
# How Swift imports C APIs
2
2
3
- When Swift imports a module or parses a bridging header from a C-based language
3
+ When Swift imports a module, or parses a bridging header from a C-based language
4
4
(C, Objective-C), the APIs are mapped into Swift APIs and can be used directly
5
5
from Swift code. This provides the basis for Swift's Foreign Function Interface
6
6
(FFI), providing interoperability with existing libraries written in C-based
7
- languages. This document describes how APIs from C-based languages are mapped
8
- into Swift APIs.
7
+ languages.
9
8
10
- this document is written for a broad audience, including Swift and C users who
9
+ This document describes how APIs from C-based languages are mapped into Swift
10
+ APIs. It is written for a broad audience, including Swift and C users who
11
11
might not be language experts. Therefore, it explains some advanced concepts
12
12
where necessary.
13
13
@@ -34,17 +34,17 @@ where necessary.
34
34
* [ Typedefs] ( #typedefs )
35
35
* [ Macros] ( #macros )
36
36
37
- # Names, identifiers and keywords
37
+ ## Names, identifiers and keywords
38
38
39
- ## Unicode
39
+ ### Unicode
40
40
41
41
C (and C++) permit non-ASCII Unicode code points in identifiers. While Swift
42
42
does not permit arbitrary Unicode code points in identifiers (so compatibility
43
43
might not be perfect), it tries to allow reasonable ones. However, C,
44
44
Objective-C, and C++ code in practice does not tend to use non-ASCII code points
45
45
in identifiers, so mapping them to Swift is not an important concern.
46
46
47
- ## Names that are keywords in Swift
47
+ ### Names that are keywords in Swift
48
48
49
49
Some C and C++ identifiers are keywords in Swift. Despite that, such names are
50
50
imported as-is into Swift, because Swift permits escaping keywords to use them
@@ -74,22 +74,22 @@ func test() {
74
74
}
75
75
```
76
76
77
- ## Name translation
77
+ ### Name translation
78
78
79
79
Names of some C declarations appear in Swift differently. In particular, names
80
80
of enumerators (enum constants) go through a translation process that is
81
81
hardcoded into the compiler. For more details, see [ Name Translation from C to
82
82
Swift] ( CToSwiftNameTranslation.md ) .
83
83
84
- ## Name customization
84
+ ### Name customization
85
85
86
86
As a general principle of Swift/C interoperability, the C API vendor has broad
87
87
control over how their APIs appear in Swift. In particular, the vendor can use
88
88
the ` swift_name ` Clang attribute to customize the names of their C APIs in order
89
89
to be more idiomatic in Swift. For more details, see [ Name Translation from C to
90
90
Swift] ( CToSwiftNameTranslation.md ) .
91
91
92
- # Size, stride, and alignment of types
92
+ ## Size, stride, and alignment of types
93
93
94
94
In C, every type has a size (computed with the ` sizeof ` operator), and an
95
95
alignment (computed with ` alignof ` ).
@@ -159,7 +159,7 @@ print(MemoryLayout<CStructWithPadding>.size) // 4
159
159
print(MemoryLayout<CStructWithPadding>.stride) // 4
160
160
```
161
161
162
- # Fundamental types
162
+ ## Fundamental types
163
163
164
164
In C, certain types (` char ` , ` int ` , ` float ` etc.) are built into the language
165
165
and into the compiler. These builtin types have behaviors that are not possible
@@ -289,12 +289,12 @@ double Add(int x, long y);
289
289
func Add(_ x: CInt, _ y: CLong) -> CDouble
290
290
```
291
291
292
- # Free functions
292
+ ## Free functions
293
293
294
294
C functions are imported as free functions in Swift. Each type in the signature
295
295
of the C function is mapped to the corresponding Swift type.
296
296
297
- ## Argument labels
297
+ ### Argument labels
298
298
299
299
Imported C functions don't have argument labels in Swift by default. Argument
300
300
labels can be added by API owners through annotations in the C header.
@@ -322,7 +322,7 @@ drawString("hello", 10, 20)
322
322
drawStringRenamed("hello", x: 10, y: 20)
323
323
```
324
324
325
- ## Variadic arguments
325
+ ### Variadic arguments
326
326
327
327
C functions with variadic arguments are not imported into Swift, however, there
328
328
are no technical reasons why they can't be imported.
@@ -344,7 +344,7 @@ See also Apple's documentation about this topic: [Use a CVaListPointer to Call
344
344
Variadic
345
345
Functions] ( https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/using_imported_c_functions_in_swift#2992073 ) .
346
346
347
- ## Inline functions
347
+ ### Inline functions
348
348
349
349
Inline C functions that are defined in headers are imported as regular Swift
350
350
functions. However, unlike free functions, inline functions require the caller
@@ -356,7 +356,7 @@ the C inline function. LLVM IR for C inline functions and LLVM IR for Swift code
356
356
is put into one LLVM module, allowing all LLVM optimizations (like inlining) to
357
357
work transparently across language boundaries.
358
358
359
- # Global variables
359
+ ## Global variables
360
360
361
361
Global C variables are imported as Swift variables or constants, depending on
362
362
constness.
@@ -375,7 +375,7 @@ var NumAlpacas: CInt
375
375
let NumLlamas: CInt
376
376
```
377
377
378
- # Pointers to data
378
+ ## Pointers to data
379
379
380
380
C has one way to form a pointer to a value of type ` T ` -- ` T* ` .
381
381
@@ -420,7 +420,7 @@ void AddSecondToFirst(int *x, const long *y);
420
420
func AddSecondToFirst(_ x: UnsafeMutablePointer<CInt>!, _ y: UnsafePointer<CLong>!)
421
421
```
422
422
423
- # Nullable and non-nullable pointers
423
+ ## Nullable and non-nullable pointers
424
424
425
425
Any C pointer can be null. However, in practice, many pointers are never null.
426
426
Therefore, code often does not expect certain pointers to be null and does not
@@ -559,7 +559,7 @@ See also Apple's documentation about this topic: [Designating Nullability in
559
559
Objective-C
560
560
APIs] ( https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization/designating_nullability_in_objective-c_apis ) .
561
561
562
- # Incomplete types and pointers to them
562
+ ## Incomplete types and pointers to them
563
563
564
564
C and C++ have a notion of incomplete types; Swift does not have anything
565
565
similar. Incomplete C types are not imported in Swift in any form.
@@ -589,7 +589,7 @@ void Print(const Foo* foo);
589
589
func Print(_ foo: OpaquePointer)
590
590
```
591
591
592
- # Function pointers
592
+ ## Function pointers
593
593
594
594
C supports only one form of function pointers: ` Result (*)(Arg1, Arg2, Arg3) ` .
595
595
@@ -641,23 +641,23 @@ void qsort_annotated(
641
641
642
642
func qsort(
643
643
_ base: UnsafeMutableRawPointer!,
644
- _ nmemb: CInt ,
645
- _ size: CInt ,
644
+ _ nmemb: Int ,
645
+ _ size: Int ,
646
646
_ compar: (@convention(c) (UnsafeRawPointer?, UnsafeRawPointer?) -> CInt)!
647
647
)
648
648
649
649
func qsort_annotated(
650
650
_ base: UnsafeMutableRawPointer,
651
- _ nmemb: CInt ,
652
- _ size: CInt ,
651
+ _ nmemb: Int ,
652
+ _ size: Int ,
653
653
_ compar: @convention(c) (UnsafeRawPointer, UnsafeRawPointer) -> CInt
654
654
)
655
655
```
656
656
657
657
See also Apple's documentation about this topic: [ Using Imported C Functions in
658
658
Swift] ( https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/using_imported_c_functions_in_swift )
659
659
660
- # Fixed-size arrays
660
+ ## Fixed-size arrays
661
661
662
662
C's fixed-size arrays are imported as Swift tuples.
663
663
@@ -685,7 +685,7 @@ Fixed-size arrays are a commonly requested feature in Swift, and a good proposal
685
685
is likely to be accepted. Once Swift has fixed-size arrays natively in the
686
686
language, we can use them to improve C interoperability.
687
687
688
- # Structs
688
+ ## Structs
689
689
690
690
C structs are imported as Swift structs, their fields are mapped to stored Swift
691
691
properties. Bitfields are mapped to computed Swift properties. Swift structs
@@ -752,17 +752,17 @@ struct StructWithAnonymousStructs {
752
752
// C header imported in Swift.
753
753
struct StructWithAnonymousStructs {
754
754
struct __Unnamed_struct___Anonymous_field0 {
755
- var x: Int32
755
+ var x: CInt
756
756
init ()
757
- init (x : Int32 )
757
+ init (x : CInt )
758
758
}
759
759
struct __Unnamed_struct_containerForY {
760
- var y: Int32
760
+ var y: CInt
761
761
init ()
762
- init (y : Int32 )
762
+ init (y : CInt )
763
763
}
764
764
var __Anonymous_field0: StructWithAnonymousStructs.__Unnamed_struct___Anonymous_field0
765
- var x: Int32
765
+ var x: CInt
766
766
var containerForY: StructWithAnonymousStructs.__Unnamed_struct_containerForY
767
767
768
768
// Default initializer that sets all properties to zero.
@@ -780,7 +780,7 @@ See also Apple's documentation about this topic: [Using Imported C Structs and
780
780
Unions in
781
781
Swift] ( https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/using_imported_c_structs_and_unions_in_swift ) .
782
782
783
- # Unions
783
+ ## Unions
784
784
785
785
Swift does not have a direct equivalent to a C union. C unions are mapped to
786
786
Swift structs with computed properties that read from/write to the same
@@ -811,7 +811,7 @@ See also Apple's documentation about this topic: [Using Imported C Structs and
811
811
Unions in
812
812
Swift] ( https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/using_imported_c_structs_and_unions_in_swift ) .
813
813
814
- # Enums
814
+ ## Enums
815
815
816
816
We would have liked to map C enums to Swift enums, like this:
817
817
@@ -829,7 +829,7 @@ enum HomeworkExcuse {
829
829
``` swift
830
830
// C header imported in Swift: aspiration, not an actual mapping!
831
831
832
- enum HomeworkExcuse : UInt32 {
832
+ enum HomeworkExcuse : CUnsignedInt {
833
833
case EatenByPet
834
834
case ForgotAtHome
835
835
case ThoughtItWasDueNextWeek
@@ -841,11 +841,11 @@ However, in practice, plain C enums are mapped to Swift structs like this:
841
841
``` swift
842
842
// C header imported in Swift: actual mapping.
843
843
844
- struct HomeworkExcuse : Equatable , RawRepresentable {
845
- init (_ rawValue : UInt32 )
846
- init (rawValue : UInt32 )
847
- var rawValue: UInt32
848
- typealias RawValue = UInt32
844
+ struct HomeworkExcuse : Equatable , RawRepresentable {
845
+ init (_ rawValue : CUnsignedInt )
846
+ init (rawValue : CUnsignedInt )
847
+ var rawValue: CUnsignedInt { get }
848
+ typealias RawValue = CUnsignedInt
849
849
}
850
850
var EatenByPet: HomeworkExcuse { get }
851
851
var ForgotAtHome: HomeworkExcuse { get }
@@ -902,13 +902,6 @@ does not handle all cases available at the compilation time.
902
902
``` c
903
903
// C header.
904
904
905
- // Enum that is not explicitly marked as either open or closed.
906
- enum HomeworkExcuse {
907
- EatenByPet,
908
- ForgotAtHome,
909
- ThoughtItWasDueNextWeek,
910
- };
911
-
912
905
// An open enum: we expect to add more kinds of input devices in future.
913
906
enum InputDevice {
914
907
Keyboard,
@@ -929,30 +922,20 @@ enum CardinalDirection {
929
922
``` swift
930
923
// C header imported in Swift.
931
924
932
- struct HomeworkExcuse : Equatable , RawRepresentable {
933
- init (_ rawValue : UInt32 )
934
- init (rawValue : UInt32 )
935
- var rawValue: UInt32
936
- typealias RawValue = UInt32
937
- }
938
- var EatenByPet: HomeworkExcuse { get }
939
- var ForgotAtHome: HomeworkExcuse { get }
940
- var ThoughtItWasDueNextWeek: HomeworkExcuse { get }
941
-
942
- enum InputDevice : UInt32 {
943
- init? (rawValue : UInt32 )
944
- var rawValue: UInt32 { get }
945
- typealias RawValue = UInt32
925
+ enum InputDevice : CUnsignedInt , Hashable , RawRepresentable {
926
+ init? (rawValue : CUnsignedInt )
927
+ var rawValue: CUnsignedInt { get }
928
+ typealias RawValue = CUnsignedInt
946
929
case Keyboard
947
930
case Mouse
948
931
case Touchscreen
949
932
}
950
933
951
- @_frozen
952
- enum CardinalDirection : UInt32 {
953
- init? (rawValue : UInt32 )
954
- var rawValue: UInt32 { get }
955
- typealias RawValue = UInt32
934
+ @frozen
935
+ enum CardinalDirection : CUnsignedInt , Hashable , RawRepresentable {
936
+ init? (rawValue : CUnsignedInt )
937
+ var rawValue: CUnsignedInt { get }
938
+ typealias RawValue = CUnsignedInt
956
939
case East
957
940
case West
958
941
case North
@@ -991,12 +974,12 @@ numeric and typed values.
991
974
// Converting enum values to integers and back.
992
975
993
976
var south: CardinalDirection = .South
994
- // var southAsInteger: UInt32 = south // error: type mismatch
995
- var southAsInteger: UInt32 = south.rawValue // = 3
996
- var southAsEnum = CardinalDirection (rawValue : 3 ) // = South
977
+ // var southAsInteger: CUnsignedInt = south // error: type mismatch
978
+ var southAsInteger: CUnsignedInt = south.rawValue // = 3
979
+ var southAsEnum = CardinalDirection (rawValue : 3 ) // = . South
997
980
```
998
981
999
- # Typedefs
982
+ ## Typedefs
1000
983
1001
984
C typedefs are generally mapped to Swift typealiases, except for a few common C
1002
985
coding patterns that are handled in a special way.
@@ -1027,7 +1010,7 @@ struct Point {
1027
1010
}
1028
1011
```
1029
1012
1030
- # Macros
1013
+ ## Macros
1031
1014
1032
1015
C macros are generally not imported in Swift. Macros that define constants are
1033
1016
imported as readonly variables.
0 commit comments