iOS - Swift 与 C 语言交互编程

前言

  • 作为一种可与 Objective-C 相互调用的语言,Swift 也具有一些与 C 语言的类型和特性,如果你的代码有需要,Swift 也提供了和常见的 C 代码结构混合编程的编程方式。

1、基本数据类型

  • Swift 提供了一些和 C 语言的基本类型如 char,int,float,double 等价的 Swift 基本数据类型。然而,这些 Swift 的核心基本类型之间并不能隐式的相互转换,如 Int。因此,只有你的代码明确要求它们时再使用这些类型,而 Int 可以在任何你想使用它的时候使用。

    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

2、枚举

  • Swift 引进了用宏 NS_ENUM 来标记的任何 C 风格的枚举类型。这意味着无论枚举值是在系统框架还是在自定义的代码中定义的,当他们导入到 Swift 时,他们的前缀名称将被截断。例如,看这个 Objective-C 枚举:

        // Objective-C
    
        typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
    
            UITableViewCellStyleDefault,
            UITableViewCellStyleValue1,
            UITableViewCellStyleValue2,
            UITableViewCellStyleSubtitle
        };
  • 在 Swift 中这样来实现:
        // Swift 
    
        enum UITableViewCellStyle:Int {
    
            case Default
            case Value1
            case Value2
            case Subtitle
        }
  • 当您需要指向一个枚举值时,使用以点 (.) 开头的枚举名称:
        // Swift
    
        let cellStyle:UITableViewCellStyle = .Default
  • Swift 也引进了标有 NS_OPTIONS 宏选项。而选项的行为类似于引进的枚举,选项还可以支持一些位操作,如 &,| 和 ~。在 Objective-C 中,你用一个空的选项设置标示恒为零 (0)。在 Swift 中,使用 nil 代表没有任何选项。

3、指针

  • Swift 尽可能避免让您直接访问指针。然而,当您需要直接操作内存的时候,Swift 也为您提供了多种指针类型。下面的表使用 Type 作为占位符类型名称来表示语法的映射。

    • 对于参数,使用以下映射:

      C 句法 Swift 句法
      const void * CConstVoidPointer
      void * CConstPointer<Type>
      const Type * CUnsignedChar
      Type * CMutablePointer<Type>
    • 对于返回类型,变量和参数类型的多层次指针,使用以下映射:
      C 句法 Swift 句法
      void * COpaquePointer
      Type * UnsafePointer<Type>
    • 对于类(class)类型,使用以下映射:
      C 句法 Swift 句法
      Type * const * CConstPointer<Type>
      Type * __strong * CMutablePointer<Type>
      Type ** AutoreleasingUnsafePointer<Type>
  • 1)C 可变指针:
    • 当一个函数被声明为接受 CMutablePointer<Type> 参数时,这个函数可以接受下列任何一个类型作为参数:

      • nil,作为空指针传入
      • 一个 CMutablePointer<Type> 类型的值
      • 一个操作数是 Type 类型的左值的输入输出表达式,作为这个左值的内存地址传入
      • 一个输入输出 Type[] 值,作为一个数组的起始指针传入,并且它的生命周期将在这个调用期间被延长
      • 如果您像这样声明了一个函数:
            // Swift
        
            func takesAMutablePointer(x:CMutablePointer<Float>) { /*...*/ }
      • 那么您可以使用以下任何一种方式来调用这个函数:
            // 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)
    • 当函数被声明使用一个 CMutableVoidPointer 参数,那么这个函数接受任何和 CMutablePointer<Type> 相似类型的 Type 操作数。
      • 如果您这样定义了一个函数:

            // Swift
        
            func takesAMutableVoidPointer(x:CMutableVoidPointer) { /*...*/ }
      • 那么您可以使用以下任何一种方式来调用这个函数:
            // 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)
  • 2)C 常指针:
    • 当一个函数被声明为接受 CConstPointer<Type> 参数时,这个函数可以接受下列任何一个类型作为参数:

      • nil,作为空指针传入
      • 一个 CMutablePointer<Type>,CMutableVoidPointer,CConstPointer<Type>,CConstVoidPointer,或者在必要情况下转换成 CConstPointer<Type>AutoreleasingUnsafePointer<Type>
      • 一个操作数是 Type 类型的左值的输入输出表达式,作为这个左值的内存地址传入
      • 一个 Type[] 数组值,作为一个数组的起始指针传入,并且它的生命周期将在这个调用期间被延长
        • 如果您这样定义了一个函数:

              // Swift
          
              func takesAConstPointer(x:CConstPointer<Float>) { /*...*/ }
        • 那么您可以使用以下任何一种方式来调用这个函数:
              // Swift
          
              var x:Float = 0.0
              var p:CConstPointer<Float> = nil
          
              takesAConstPointer(nil)
              takesAConstPointer(p)
              takesAConstPointer(&x)
              takesAConstPointer([1.0, 2.0, 3.0])
      • 当函数被声明使用一个 CConstVoidPointer 参数,那么这个函数接受任何和 CConstPointer<Type> 相似类型的 Type 操作数。
        • 如果您这样定义了一个函数:

              // Swift
          
              func takesAConstVoidPointer(x:CConstVoidPointer) { /*...*/ }
        • 那么您可以使用以下任何一种方式来调用这个函数:
              // 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)自动释放不安全指针:
    • 当一个函数被声明为接受 AutoreleasingUnsafePointer<Type> 参数时,这个函数可以接受下列任何一个类型作为参数:

      • nil,作为空指针传入
      • 一个 AutoreleasingUnsafePointer<Type>
      • 其操作数是原始的,复制到一个临时的没有所有者的缓冲区的一个输入输出表达式,该缓冲区的地址传递给调用,并返回时,缓冲区中的值加载,保存,并重新分配到操作数。
      • 注意:这个列表没有包含数组。
      • 如果您这样定义了一个函数:
            // Swift
        
            func takesAnAutoreleasingPointer(x:AutoreleasingUnsafePointer<NSDate?>) { /*...*/ }
      • 那么您可以使用以下任何一种方式来调用这个函数:
            // Swift
        
            var x:NSDate? = nil
            var p:AutoreleasingUnsafePointer<NSDate?> = nil
        
            takesAnAutoreleasingPointer(nil)
            takesAnAutoreleasingPointer(p)
            takesAnAutoreleasingPointer(&x)
      • 注意:C 语言函数指针没有被 Swift 引进。

4、全局常量

  • 在 C 和 Objective-C 语言源文件中定义的全局常量会自动地被 Swift 编译引进并做为 Swift 的全局常量。

5、预处理指令

  • Swift 编译器不包含预处理器。取而代之的是它充分利用了编译时属性生成配置和语言特性来完成相同的功能。因此 Swift 没有引进预处理指令。
  • 1)简单宏
    • 在 C 和 Objective-C,您通常使用的 #define 指令定义的一个宏常数,在 Swift,您可以使用全局常量来代替。例如: 一个全局定义 #define FADE_ANIMATION_DURATION 0.35,在 Swift可以使用 let FADE_ANIMATION_DURATION = 0.35 来更好的表述。由于简单的用于定义常量的宏会被直接被映射成 Swift 全局量,Swift 编译器会自动引进在 C 或 Objective-C 源文件中定义的简单宏。
  • 2)复杂宏
    • 在 C 和 Objective-C 中使用的复杂宏在 Swift 中并没有与之对应的定义。复杂宏是那些不用来定义常量的宏,而是用来定义包含小括号 () 函数的宏。您在 C 和 Objective-C 使用复杂的宏是用 来避免类型检查的限制和相同代码的重复劳动。然而,宏也会产生 Bug 和重构的困难。在 Swift 中你可以直接使用函数和泛型来达到同样的效果。因此,在 C 和 Objective-C 源文件中定义的复杂宏在 Swift 是不能使用的。
  • 3)编译配置
    • Swift 代码和 Objective-C 代码以不同的方式进行条件编译。Swift 代码可以根据生成配置的评价配进行有条件的编译。生成配置包括 truefalse 字面值,命令行标志,和下表中的平台测试函数。您可以使用 -D <#Flag#> 指定命令行标志。

      函数 有效参数
      os() OSX, iOS
      arch() x86_64, arm, arm64, i386
      • 注意:arch(arm) 的生成配置不会为 64 位 arm 设备返回 true,当代码运行在为 32 位的 iOS 模拟器器时,arch(i386) 的生成配置返回 true
  • 一个简单的条件编译需要以下代码格式:
        #if build configuration
            statements
        #else
            statements
        #endif
  • 一个由零个或多个有效的 Swift 语句声明的 statements,可以包括表达式,语句和控制流语句。您可以添加额外的构建配置要求,条件编译说明用 &&|| 操作符以及 ! 操作符,添加条件控制块用 #elseif
        #if build configuration && !build configuration
            statements
        #elseif build configuration
            statements
        #else
            statements
        #endif
  • 与 C 语言编译器的条件编译相反,Swift 条件编译语句必须完全是自包含和语法有效的代码块。这是因为 Swift 代码即使没有被编译,也要全部进行语法检查。
时间: 2024-07-28 20:04:25

iOS - Swift 与 C 语言交互编程的相关文章

Swift和C语言混合编程教程_Swift

作为一种可与 Objective-C 相互调用的语言,Swift 也具有一些与 C 语言的类型和特性,如果你的代码有需要,Swift 也提供了和常见的 C 代码结构混合编程的编程方式. 基本数据类型 Swift 提供了一些和 C 语言的基本类型如char,int,float,double等价的 Swift 基本数据类型.然而,这些 Swift 的核心基本类型之间并不能隐式的相互转换,如 Int.因此,只有你的代码明确要求它们时再使用这些类型,而 Int 可以在任何你想使用它的时候使用. C 类型

Swift 中的面向协议编程是如何点亮我的人生的

本文讲的是Swift 中的面向协议编程是如何点亮我的人生的, 面向对象编程至今已经使用了数十年了,并且成为了构建大型软件约定俗成的标准.作为iOS编程的中心思想,遵循面向对象规范来编写一个 iOS 的应用几乎不可能实现.虽然面向对象有很多优点比如封装性,访问控制和抽象性,但是它也自带有固有的缺点. 大多数类的情况下,当一个单继承的类需要更多不同类中的函数功能时,你会倾向于使用多继承来实现. 但是大部分的编程语言不支持这一特性,而且会导致类的继承关系变得复杂. 在多线程环境下,如果所有对象在函数中

[译] 原生 iOS(Swift) 和 React-Native 的性能比较

本文讲的是[译] 原生 iOS(Swift) 和 React-Native 的性能比较, 原文地址:Comparing the Performance between Native iOS (Swift) and React-Native 原文作者:John A. Calderaio 译文出自:掘金翻译计划 译者:Deepmissea 校对者:gy134340,Danny1451 原生 iOS(Swift) 和 React-Native 的性能比较 React-Native 是一个混合的移动框架

Swift与C语言指针结合使用实例

  这篇文章主要介绍了Swift与C语言指针结合使用实例,本文讲解了用以输入/输出的参数指针.作为数组使用的参数指针.用作字符串参数的指针.指针参数转换的安全性等内容,需要的朋友可以参考下 Objective-C和C的API常常会需要用到指针.Swift中的数据类型都原生支持基于指针的Cocoa API,不仅如此,Swift会自动处理部分最常用的将指针作为参数传递的情况.这篇文章中,我们将着眼于在Swift中让C语言指针与变量.数组和字符串共同工作. ####用以输入/输出的参数指针 C和Obj

iOS开发系列--C语言之基础知识

当前移动开发的趋势已经势不可挡,这个系列希望浅谈一下个人对IOS开发的一些见解,这个IOS系列计划从几个角度去说IOS开发: C语言 OC基础 IOS开发(iphone/ipad) Swift 这么看下去还有大量的内容需要持续补充,但是今天我们从最基础的C语言开始,C语言部分我将分成几个章节去说,今天我们简单看一下C的一些基础知识,更高级的内容我将放到后面的文章中. 今天基础知识分为以下几点内容(注意:循环.条件语句在此不再赘述): Hello World 运行过程 数据类型 运算符 常用函数

iOS swift 总结NavigationController出现问题及解决方法_IOS

IOS swift 总结NavigationController出现问题及解决方法 最近用Swift语言做了一些iOS项目,颇有些心得,记下一些深刻的问题造福自己,服务大家 1.以NavigationController做为容器后状态栏的字体颜色就会不在受系统的控制,要在NavigationController中的根ViewController中设置方可生效,代码如下: self.navigationController!.navigationBar.barStyle = UIBarStyle.

C语言高效编程的几招小技巧

  这篇文章主要介绍了C语言高效编程的几招小技巧,本文讲解了以空间换时间.用数学方法解决问题以及使用位操作等编辑技巧,并给出若干方法和代码实例,需要的朋友可以参考下 引言: 编写高效简洁的C语言代码,是许多软件工程师追求的目标.本文就工作中的一些体会和经验做相关的阐述,不对的地方请各位指教. 第1招:以空间换时间 计算机程序中最大的矛盾是空间和时间的矛盾,那么,从这个角度出发逆向思维来考虑程序的效率问题,我们就有了解决问题的第1招--以空间换时间. 例如:字符串的赋值. 方法A,通常的办法: 代

关于linux c语言多线程编程的问题

问题描述 关于linux c语言多线程编程的问题 /* 以生产者和消费者模型问题来阐述Linux线程的控制和通信你 生产者线程将生产的产品送入缓冲区,消费者线程则从中取出产品. 缓冲区有N个,是一个环形的缓冲池. */#include #include #define BUFFER_SIZE 16 struct prodcons{ int buffer[BUFFER_SIZE];/*实际存放数据的数组*/ pthread_mutex_t lock;/*互斥体lock,用于对缓冲区的互斥操作*/

c语言-不知道是不是笛卡尔心形函数C语言的编程,,

问题描述 不知道是不是笛卡尔心形函数C语言的编程,, private void Form4_Load(object sender, EventArgs e) { this.BackColor = Color.Black; this.Size = new Size(400, 400); Panel panel = new Panel(); panel.Size = new Size(350, 350); panel.Paint += new PaintEventHandler(panel_Pain