Mixed programming tutorials for Swift and C languages

  • 2020-05-07 20:31:30
  • OfStack

As a language that can be intercalled with Objective-C, Swift also has some of the types and features of the C language, and Swift also provides a programming mix with the common C code structure if your code requires it.

basic data type

Swift provides some basic Swift data types equivalent to char, int, float, double and C. However, these core base types of Swift cannot be implicitly converted to each other, such as Int. So, use these types only if your code specifically requires them, and Int can be used whenever you want.

C 类型 Swift 类型
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

enumeration

Swift introduces any C-style enumerated type tagged with the macro NS_ENUM. This means that whether enumeration values are defined in the system framework or in custom code, their prefix names are truncated when they are imported into Swift. For example, look at the Objective-C enumeration:


//Objective-C
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
    UITableViewCellStyleDefault,
    UITableViewCellStyleValue1,
    UITableViewCellStyleValue2,
    UITableViewCellStyleSubtitle
};

In Swift, it is implemented as follows:

//Swift
enum UITableViewCellStyle: Int {
    case Default
    case Value1
    case Value2
    case Subtitle
}

When you need to point to an enumeration value, use the enumeration name beginning with the point (.) :


//Swift
let cellStyle: UITableViewCellStyle = .Default

Swift also introduces the macro option marked NS_OPTIONS. Options behave like imported enumerations, and can support 1-bit operations such as &, |, and ~. In Objective-C, you set the flag to zero (0) with an empty option. In Swift, using nil means there are no options.

pointer

Swift avoids giving you direct access to Pointers as much as possible. However, Swift also provides you with a variety of pointer types when you need to directly manipulate memory. The following table USES Type as the placeholder type name to represent the mapping of the syntax.
For parameters, use the following mapping:

C 句法 Swift 句法
const void * CConstVoidPointer
void * CMutableVoidPointer
const Type * CConstPointer<Type>
Type * CMutablePointer<Type>


For multi-level Pointers to return types, variables, and parameter types, use the following mapping:

C 句法 Swift 句法
void * COpaquePointer
Type * UnsafePointer<Type>


For the class (class) type, use the following mapping:

C 句法 Swift 句法
Type * const * CConstPointer<Type>
Type * __strong * CMutablePointer<Type>
Type ** AutoreleasingUnsafePointer<Type>

C variable pointer

When a function is declared to accept CMutablePointer < Type > This function can take any of the following types as arguments:

The & # 8226; nil, passed in as a null pointer
The & # 8226; 1 CMutablePointer < Type > The value of the type
The & # 8226; An operand is an input-output expression of an lvalue of type Type, passed as the memory address of this lvalue
The & # 8226; One input-output Type[] value is passed in as the starting pointer to an array, and its life cycle is extended during this call

If you declare a function like this:


//Swift
func takesAMutablePointer(x: CMutablePointer<Float>) { /*...*/ }

Then you can call this function in any of the following ways:


//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 to use 1 CMutableVoidPointer parameter, the function accepts any and CMutablePointer < Type > Type operand of a similar type.

If you define a function like this:


//Swift
func takesAMutableVoidPointer(x: CMutableVoidPointer) { /* ... */ }

Then you can call this function in any of the following ways:

//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)

C regular pointer

When a function is declared to accept CConstPointer < Type > This function can take any of the following types as arguments:

The & # 8226; nil, passed in as a null pointer
The & # 8226; 1 CMutablePointer < Type > , CMutableVoidPointer, CConstPointer < Type > , CConstVoidPointer, or convert to CConstPointer if necessary < Type > The AutoreleasingUnsafePointer < Type > value
The & # 8226; An operand is an input-output expression of an lvalue of type Type, passed as the memory address of this lvalue
The & # 8226; An Type[] array value is passed in as the starting pointer to an array, and its life cycle is extended during this call


//Swift
func takesAConstPointer(x: CConstPointer<Float>) { /*...*/ }

Then you can call this function in any of the following ways:


//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 to use an CConstVoidPointer parameter, the function accepts any and CConstPointer < Type > Type operand of a similar type. The & # 65532; If you define a function like this:


//Swift 
func takesAConstVoidPointer(x: CConstVoidPointer) { /* ... */ }

Then you can call this function in any of the following ways:


//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])

automatically releases the unsafe pointer

When a function is declared to accept AutoreleasingUnsafePointer < Type > This function can take any of the following types as arguments:

The & # 8226; nil, passed in as a null pointer
The & # 8226; 1 AutoreleasingUnsafePointer < Type > value
The & # 8226; Its operands are primitive, copied to an I/o expression of a temporary, owner-less buffer, whose address is passed to the call, and returned when the values in the buffer are loaded, saved, and reassigned to the operands.

Note: this list does not contain an array.

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: the C language function pointer was not introduced by Swift.

global constant

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

preprocessing instruction

The Swift compiler does not contain a preprocessor. Instead, it takes full advantage of compile-time properties, generated configurations, and language features to do the same. Therefore, Swift does not introduce preprocessing instructions.

simple macro

In C and Objective-C, you typically use the #define directive to define 1 macro constant, and in Swift, you can use global constants instead. For example, a global definition #define FADE_ANIMATION_DURATION 0.35 can be better expressed in Swift by let FADE_ANIMATION_DURATION = 0.35. Since simple macros used to define constants are mapped directly to Swift global quantities, the Swift compiler automatically introduces simple macros defined in C or Objective-C source files.

complex macro

The complex macros used in C and Objective-C have no corresponding definition in Swift. Complex macros are macros that are not used to define constants, but instead are used to define functions that contain braces (). Your use of complex macros in C and Objective-C is designed to avoid restrictions on type checking and duplication of effort with the same code. However, macros also create Bug 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 are not available in Swift.

compilation configuration

The Swift code and Objective-C code are conditionally compiled in different ways. The Swift code can be conditionally compiled based on the evaluation of the build configuration. The build configuration includes the true and false literals, command-line flags, and platform test functions in the following table. You can use -D < # # Flag > Specifies the command line flag.

函数 有效参数
os() OSX, iOS
arch() x86_64, arm, arm64, i386

Note: the build configuration of arch(arm) does not return true for the 64-bit arm device, and the build configuration of arch(i386) returns true when the code runs on the 32-bit ios emulator.

1 simple conditional compilation requires the following code format:


#if build configuration
    statements
#else
    statements
#endif

An statements declared by zero or more valid Swift statements can include expressions, statements, and control flow statements. You can add additional build configuration requirements, conditional compilation instructions with && and | | operators as well as! Operator, add conditional control block with # elseif:


#if build configuration && !build configuration
    statements
#elseif build configuration
    statements
#else
    statements
#endif

In contrast to conditional compilation in the C language compiler, Swift conditional compilation statements must be completely self-contained and syntactically valid blocks of code. This is because the Swift code is syntactically checked in its entirety, even if it is not compiled.


Related articles: