Swift and C language mixed programming

foreword

  • As a language that can call each other with Objective-C, Swift also has some types and features of the C language. If your code needs it, Swift also provides a programming method that mixes programming with common C code structures.

1. Basic data types

  • Swift provides some basic types that are char,int,float,doubleequivalent Swift primitive data types. However, there is no implicit conversion between these Swift core primitive types, eg Int. Therefore, use these types only when your code explicitly requires them, and Intuse you want.

    Type C Swift type
    bool CBool
    char, signed char CChar
    unsigned char CUnsignedChar
    short CShort
    unsigned short CUnsignedShort
    int CInt
    unsigned int CUnsignedInt
    long CLong
    unsigned long CUnsignedLong
    long long CLongLong
    unsigned long long CUnsignedLongLong
    wchar_t CWideChar
    char16_t CChar16
    char32_t CChar32
    float CFloat
    double CDouble

2. Enumeration

  • Swift introduces any C-style enumeration type marked NS_ENUMwith . This means that whether enum values ​​are defined in the system framework or in custom code, when they are imported into Swift, their prefix names will be truncated.

  • Swift also introduced options marked with NS_OPTIONSmacros . While options behave like the introduced enumerations, options can also support some bit manipulations, eg &,| 和 ~.
  • In Objective-C, you set the flag to be always zero (0) with an empty option. In Swift, use nil for no options.

  • Look at this Objective-C enum

    // Objective-C
    
    typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
    
        UITableViewCellStyleDefault,
        UITableViewCellStyleValue1,
        UITableViewCellStyleValue2,
        UITableViewCellStyleSubtitle
    };
  • Do this in Swift

    // Swift 
    
    enum UITableViewCellStyle: Int {
    
        case Default
        case Value1
        case Value2
        case Subtitle
    }
  • When you need to point to an enum value, use the enum name starting with a dot (.)

    // Swift
    
    let cellStyle: UITableViewCellStyle = .Default

3. Pointer

  • Swift avoids letting you directly access pointers whenever possible. However, Swift also provides you with a variety of pointer types when you need to manipulate memory directly. The following table uses Type as a placeholder type name to represent the mapping of grammars.

  • For parameters, use the following mapping:

    C syntax Swift syntax
    const void * CConstVoidPointer
    void * CConstPointer<Type>
    const Type * CUnsignedChar
    Type * CMutablePointer<Type>
  • For multi-level pointers of return types, variable and parameter types, the following mappings are used:

    C syntax Swift syntax
    void * COpaquePointer
    Type * UnsafePointer<Type>
  • For class types, use the following mapping:

    C syntax Swift syntax
    Type * const * CConstPointer<Type>
    Type * __strong * CMutablePointer<Type>
    Type ** AutoreleasingUnsafePointer<Type>

3.1 C mutable pointers

  • When a function is declared to accept CMutablePointer<Type>parameters , the function can accept any of the following types as parameters.

    • nil, passed in as a null pointer
    • a value of CMutablePointer<Type>type
    • an input-output expression whose operand is an lvalue of Typetype , passed in as the memory address of this lvalue
    • An input and output Type[]value , passed in as the start pointer of an array, and whose lifetime will be extended during this call

    • If you declare a function like this

      // Swift
      
      func takesAMutablePointer(x: CMutablePointer<Float>) { /*...*/ }
    • Then you can use any of the following ways to call this function

      // Swift
      
      var x: Float = 0.0
      var p: CMutablePointer<Float> = nil
      var a: [Float] = [1.0, 2.0, 3.0]
      
      takesAMutablePointer(nil)
      takesAMutablePointer(p)
      takesAMutablePointer(&x)
      takesAMutablePointer(&a)
  • When a function is declared with a CMutableVoidPointerparameter , then the function accepts any operandCMutablePointer<Type> of similar type .Type

    • If you define a function like this

      // Swift
      
      func takesAMutableVoidPointer(x: CMutableVoidPointer) { /*...*/ }
    • Then you can use any of the following ways to call this function

      // Swift
      
      var x: Float = 0.0, y:Int = 0
      var p: CMutablePointer<Float> = nil, q: CMutablePointer<Int> = nil
      var a: [Float] = [1.0, 2.0, 3.0], b: Int = [1, 2, 3]
      
      takesAMutableVoidPointer(nil)
      takesAMutableVoidPointer(p)
      takesAMutableVoidPointer(q)
      takesAMutableVoidPointer(&x)
      takesAMutableVoidPointer(&y)
      takesAMutableVoidPointer(&a)
      takesAMutableVoidPointer(&b)

3.2 C constant pointers

  • When a function is declared to accept CConstPointer<Type>parameters , the function can accept any of the following types as parameters.

    • nil, passed in as a null pointer
    • one , or the value convertedCMutablePointer<Type>,CMutableVoidPointer,CConstPointer<Type>,CConstVoidPointer to if necessaryCConstPointer<Type>AutoreleasingUnsafePointer<Type>
    • an input-output expression whose operand is an lvalue of Typetype , passed in as the memory address of this lvalue
    • an Type[]array value, passed in as the start pointer of an array whose lifetime will be extended during this call

    • If you define a function like this

      // Swift
      
      func takesAConstPointer(x: CConstPointer<Float>) { /*...*/ }
    • Then you can use any of the following ways to call this function

      // Swift
      
      var x: Float = 0.0
      var p: CConstPointer<Float> = nil
      
      takesAConstPointer(nil)
      takesAConstPointer(p)
      takesAConstPointer(&x)
      takesAConstPointer([1.0, 2.0, 3.0])
  • When a function is declared with a CConstVoidPointerparameter , then the function accepts any operandCConstPointer<Type> of similar type .Type

    • If you define a function like this

      // Swift
      
      func takesAConstVoidPointer(x: CConstVoidPointer) { /*...*/ }
    • Then you can use any of the following ways to call this function

      // Swift
      var x: Float = 0.0, y: Int = 0
      var p: CConstPointer<Float> = nil, q: CConstPointer<Int> = nil
      
      takesAConstVoidPointer(nil)
      takesAConstVoidPointer(p)
      takesAConstVoidPointer(q)
      takesAConstVoidPointer(&x)
      takesAConstVoidPointer(&y)
      takesAConstVoidPointer([1.0, 2.0, 3.0])
      takesAConstVoidPointer([1, 2, 3])

3.3 Automatic release of unsafe pointers

  • When a function is declared to accept AutoreleasingUnsafePointer<Type>parameters , the function can accept any of the following types as parameters.

    • nil, passed in as a null pointer
    • a AutoreleasingUnsafePointer<Type>value
    • An in-out expression whose operands are raw, copied into a temporary unowned buffer, the address of the buffer passed to the call, and on return, the value in the buffer is loaded, saved, and reallocated to the operand.

    • Note: This list does not contain arrays.

    • If you define a function like this

      // Swift
      
      func takesAnAutoreleasingPointer(x: AutoreleasingUnsafePointer<NSDate?>) { /*...*/ }
    • Then you can call this function in any of the following ways:

      // Swift
      
      var x: NSDate? = nil
      var p: AutoreleasingUnsafePointer<NSDate?> = nil
      
      takesAnAutoreleasingPointer(nil)
      takesAnAutoreleasingPointer(p)
      takesAnAutoreleasingPointer(&x)
    • Note: C function pointers were not introduced by Swift.

4. Global constants

  • Global constants defined in C and Objective-C language source files are automatically imported by Swift compilation as Swift global constants.

5. Preprocessing instructions

  • The Swift compiler does not include a preprocessor. Instead, it makes full use of compile-time properties to generate configuration and language features to accomplish the same functionality. So Swift doesn't introduce preprocessor directives.

5.1 Simple macros

  • A macro constant defined by the #definedirective can be replaced by a global constant in Swift. Since simple macros used to define constants are directly mapped to Swift globals, the Swift compiler automatically introduces simple macros defined in C or Objective-C source files.

  • For example: a global definition #define FADE_ANIMATION_DURATION 0.35can let FADE_ANIMATION_DURATION = 0.35be .

5.2 Complex macros

  • Complex macros used in C and Objective-C do not have corresponding definitions in Swift. Complex macros are those macros that are not used to define constants, but are used to define functions that contain parentheses ( ). The complex macros you use in C and Objective-C are there to avoid the constraints of type checking and duplication of the same code. However, macros can also create bugs and refactoring difficulties. In Swift you can use functions and generics directly to achieve the same effect. Therefore, complex macros defined in C and Objective-C source files cannot be used in Swift.

5.3 Compile configuration

  • Swift code and Objective-C code are conditionally compiled in different ways. Swift code can be conditionally compiled based on the evaluation profile of the build configuration. The build configuration includes trueand falseliterals, command-line flags, and the platform test functions in the table below. You can -D <#Flag#>specify command line flags with .

    function valid parameters
    os() OSX, iOS
    arch() x86_64, arm, arm64, i386
    • Note: arch(arm)The build configuration is not returned for 64-bit arm devices, and the build configuration is returned when truethe code is run on an iOS simulator that is 32-bit .arch(i386)true
  • A simple conditional compilation requires the following code format.

    #if build configuration
        statements
    #else
        statements
    #endif
  • A declaration by zero or more valid Swift statements statements, which can include expressions, statements, and control flow statements. You can add additional build configuration requirements, conditional compilation instructions with &&and ||operators !and operators, and conditional control blocks #elseif.

    #if build configuration && !build configuration
        statements
    #elseif build configuration
        statements
    #else
        statements
    #endif
  • Contrary to the C compiler's conditional compilation, Swift conditional compilation statements must be entirely self-contained and syntactically valid blocks of code. This is because Swift code is all syntax checked even if it is not compiled.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324821011&siteId=291194637