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 源文件中定义的简单宏。
- 在 C 和 Objective-C,您通常使用的 #define 指令定义的一个宏常数,在 Swift,您可以使用全局常量来代替。例如: 一个全局定义
- 2)复杂宏
- 在 C 和 Objective-C 中使用的复杂宏在 Swift 中并没有与之对应的定义。复杂宏是那些不用来定义常量的宏,而是用来定义包含小括号 () 函数的宏。您在 C 和 Objective-C 使用复杂的宏是用 来避免类型检查的限制和相同代码的重复劳动。然而,宏也会产生 Bug 和重构的困难。在 Swift 中你可以直接使用函数和泛型来达到同样的效果。因此,在 C 和 Objective-C 源文件中定义的复杂宏在 Swift 是不能使用的。
- 3)编译配置
Swift 代码和 Objective-C 代码以不同的方式进行条件编译。Swift 代码可以根据生成配置的评价配进行有条件的编译。生成配置包括
true
和false
字面值,命令行标志,和下表中的平台测试函数。您可以使用-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 代码即使没有被编译,也要全部进行语法检查。
iOS - Swift 与 C 语言交互编程的更多相关文章
- Swift 与 C 语言混合编程
前言 作为一种可与 Objective-C 相互调用的语言,Swift 也具有一些与 C 语言的类型和特性,如果你的代码有需要,Swift 也提供了和常见的 C 代码结构混合编程的编程方式. 1.基本 ...
- iOS: 学习笔记, Swift与C指针交互(译)
Swift与C指针交互 Objective-C和C API经常需要使用指针. 在设计上, Swift数据类型可以自然的与基于指针的Cocoa API一起工作, Swift自动处理几种常用的指针参数. ...
- 从Go、Swift出发:语言的选择需谨慎
本文转自 : http://www.csdn.net/article/2014-12-09/2823025 摘要:无论是开源的Go,还是闭源的Swift,新的语言总是利弊一体.不过可以确定的是,新的语 ...
- iOS开发系列--C语言之基础知识
概览 当前移动开发的趋势已经势不可挡,这个系列希望浅谈一下个人对IOS开发的一些见解,这个IOS系列计划从几个角度去说IOS开发: C语言 OC基础 IOS开发(iphone/ipad) Swift ...
- 为什么还坚持.NET? 找一门适合自己的语言去做编程
为什么还坚持.NET? 找一门适合自己的语言去做编程 接触了.NET快十二年了,现在专注于分布式服务的开发. 中间经历过各种编程语言的诱惑,ios等. 前几年才对自己有比较明确的定位 技术上:找到适合 ...
- iOS Swift 模块练习/swift基础学习
SWIFT项目练习 SWIFT项目练习2 iOS Swift基础知识代码 推荐:Swift学习使用知识代码软件 0.swift中的宏定义(使用方法代替宏) 一.视图 +控件 1.UIImag ...
- Go语言 并发编程
Go语言 并发编程 作者:Eric 微信:loveoracle11g 1.创建goroutine // 并行 是两个队列同时使用两台咖啡机 // 并发 是两个队列交替使用一台咖啡机 package m ...
- swift是强类型语言
swift是强类型语言 所有的变量必须先声明,后使用: 指定类型的变量只能接收类型与之匹配的值. 强类型:变量的类型明确,变量的赋值必须符合类型约束:变量的类型转化必须显式进行. 强类型:类型规则的制 ...
- iOS Swift WisdomHUD 提示界面框架
iOS Swift WisdomHUD 提示界面框架 Framework Use profile(应用简介) 一:WisdomHUD简介 今天给大家介绍一款iOS的界面显示器:WisdomHUD,W ...
随机推荐
- Akka.NET
https://github.com/akkadotnet Akka是什么? 可扩展的分布式实时事务处理 编写正确的并发,容错和可扩展的应用程序是太难了.大多数时候,这是因为我们使用了错误的工具和错误 ...
- jenkins+jmeter+ant搭建接口测试平台
接口测试的重点是检查数据的交换,传递和控制管理过程以及系统间的相互逻辑依赖关系. 接口测试的流程 项目启动后,测试人员要尽早拿到接口测试文档. 开始编写接口测试用例 将接口测试用例部署到持续集成的测试 ...
- matlab读入矩阵数据
方法: 很简单,把矩阵数据存到excel里,然后存成cvs的格式,就是把每行数据之间用‘,’分隔:行与行之间用‘\n’保存. 举例: 假设cvs为test_nnfeature.txt,后缀可以改啦,只 ...
- Dynamics AX 2012 R2 在报表上显示和打印条码
AX中有对条码操作的封装,用其生成BarCodeString类型的值,再配合barcode128字体,即可在显示出条码. 废话不说,上代码. BarcodeCode128 barCod ...
- restful 注解
@Path @Path 注释被用来描述根资源.子资源方法或子资源的位置.value 值可以包含文本字符.变量或具有定制正则表达式的变量. @GET.@POST.@PUT.@DELETE.@HEAD @ ...
- Asp.net Vnext Filters
ASP.NET MVC 提供Filters(筛选器)之前或之后调用操作方法执行筛选逻辑,和AOP面向切面编程一样. 本文已经同步到<Asp.net Vnext 系列教程 >中] 本章主要介 ...
- Oracle中左右外连接详解
数据表的连接有: 1.内连接(自然连接): 只有两个表相匹配的行才能在结果集中出现 2.外连接: 包括 (1)左外连接(左边的表不加限制) (2)右外连接(右边的表不加限制) (3)全外连接(左右两 ...
- word中设置前几页为罗马数字,后几页设置为阿拉伯数字
假如第1-5页摘要部分页脚要是罗马数字,第6页开始是正文部分是阿拉伯数字,起始页为1. WORD2003 1.将光标定位在第5页末尾处,在菜单栏中依次点击“插入——分隔符——(分节符类型)下一页”.按 ...
- Winform知识点
Winform窗体常用的控件 1.按钮 Button 前缀:btn 2.文本框 TextBox 前缀:txt 3.单选按钮 RadioButton 前缀:rdo 4.复选按钮 CheckBox 前缀: ...
- https协议操作
在伪静态中加入下列代码 <IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{SERVER_PORT} 80 RewriteRul ...