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 时,他们的前缀名称将被截断。Swift 也引进了标有
NS_OPTIONS
宏选项。而选项的行为类似于引进的枚举,选项还可以支持一些位操作,如&,| 和 ~
。在 Objective-C 中,你用一个空的选项设置标示恒为零 (0)。在 Swift 中,使用 nil 代表没有任何选项。
看这个 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
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>
3.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)
3.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.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 没有引进预处理指令。
5.1 简单宏
在 C 和 Objective-C 中通常使用的
#define
指令定义的一个宏常数,在 Swift 中可以使用全局常量来代替。由于简单的用于定义常量的宏会被直接被映射成 Swift 全局量,Swift 编译器会自动引进在 C 或 Objective-C 源文件中定义的简单宏。例如: 一个全局定义
#define FADE_ANIMATION_DURATION 0.35
,在 Swift可以使用let FADE_ANIMATION_DURATION = 0.35
来更好的表述。
5.2 复杂宏
- 在 C 和 Objective-C 中使用的复杂宏在 Swift 中并没有与之对应的定义。复杂宏是那些不用来定义常量的宏,而是用来定义包含小括号 () 函数的宏。你在 C 和 Objective-C 使用复杂的宏是用来避免类型检查的限制和相同代码的重复劳动。然而,宏也会产生 Bug 和重构的困难。在 Swift 中你可以直接使用函数和泛型来达到同样的效果。因此,在 C 和 Objective-C 源文件中定义的复杂宏在 Swift 是不能使用的。
5.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 代码即使没有被编译,也要全部进行语法检查。
Swift 与 C 语言混合编程的更多相关文章
- 【转载】ANSYS的APDL与C语言混合编程(实例)
原文地址:http://www.cnblogs.com/lyq105/archive/2010/05/04/1727557.html 本文讨论的不是利用C语言为ANSYS写扩展(或者说是用户子程序), ...
- Java语言与C语言混合编程(2)--在Java中调用C语言本地库
在上一篇文章中介绍了Java语言中的native关键字,以及Java语言调用C语言的编译生成本地动态链接库(DLL)实现加法运算的小例子,本文通过一个更加详细的例子,深入讲解Java语言调用C语言的函 ...
- Java语言与C语言混合编程(1)--Java native 关键字
一. 什么是 native Method 简单地讲,一个 native Method 就是一个java调用非java代码的接口.一个 native Method 是这样一个java的方法:该方法的实现 ...
- Android程序中,内嵌ELF可执行文件-- Android开发C语言混合编程总结
前言 都知道的,Android基于Linux系统,然后覆盖了一层由Java虚拟机为核心的壳系统.跟一般常见的Linux+Java系统不同的,是其中有对硬件驱动进行支持,以避开GPL开源协议限制的HAL ...
- iOS - Swift 与 C 语言交互编程
前言 作为一种可与 Objective-C 相互调用的语言,Swift 也具有一些与 C 语言的类型和特性,如果你的代码有需要,Swift 也提供了和常见的 C 代码结构混合编程的编程方式. 1.基本 ...
- Dart 调用C语言混合编程
Dart 调用C语言本篇博客研究Dart语言如何调用C语言代码混合编程,最后我们实现一个简单示例,在C语言中编写简单加解密函数,使用dart调用并传入字符串,返回加密结果,调用解密函数,恢复字符串内容 ...
- SQL+C#:一次多语言混合编程的经验总结
1.用JAVA做,采取轮询策略: 2.用sql语言+C#混合编程,采取触发策略
- Swift语言与Objective-C语言混合编程
首先创建一个Swift的Single View工程 然后直接在工程中新建OC文件: 然后选择OC语言之后会问你是否自动创建OC和Swift的中间文件: 然后工程文件夹里就有了三个文件: 现在OC头文件 ...
- 《从零开始学Swift》学习笔记(Day 71)——Swift与C/C++混合编程之数据类型映射
原创文章,欢迎转载.转载请注明:关东升的博客 如果引入必要的头文件,在Objective-C语言中可以使用C数据类型.而在Swift语言中是不能直接使用C数据类型,苹果公司为Swift语言提供与C语言 ...
随机推荐
- ES6精简要点
没想到ES7都出来了(虽然并不大),想到自己ES6还没学完 现在就补补吧,记录下重点部分 Let的用法 用来声明块级变量 f1();function f1() { let n = 5; if (tru ...
- CSS3 根据屏幕大小显示内容(@media)
@media (min-width: 993px) { .footer .addZ1{display:none;} .footer .addZ2{display:none;} .footer . ...
- 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-5 random direction & ONB
Preface 往后看了几章,对这本书有了新的理解 上一篇,我们第一次尝试把MC积分运用到了Lambertian材质中,当然,第一次尝试是失败的,作者发现它的渲染效果和现实有些出入,所以结尾处声明要 ...
- DataTable保存为Excel或者Txt
保存为txt的时候,可保持原来的行列对齐,如下:using System; using System.Collections.Generic; using System.Text; using Sys ...
- 浅谈CSS和JQuery实现鼠标悬浮图片放大效果
对于刚刚学习网页前台设计的同学一定对图片的处理非常苦恼,那么这里简单的讲解一下几个图片处理的实例. 以.net为平台,微软的Visual Studio 2013为开发工具,当然前台技术还是采用CSS3 ...
- HDU.5628.Clarke and math(狄利克雷卷积 快速幂)
\(Description\) \[g(i)=\sum_{i_1|i}\sum_{i_2|i_1}\sum_{i_3|i_2}\cdots\sum_{i_k|i_{k-1}}f(i_k)\ mod\ ...
- Python图形编程探索系列-07-程序登录界面设计
设计任务 初步设计程序登录界面,详细分析设计步骤. 程序详细分析 基本框架设计 import tkinter as tk import tkinter.messagebox root = tk.Tk( ...
- Python3练习题系列(10)——项目骨架构建
目标: 如何创建<项目“骨架”目录> 包含:项目文件布局.自动化测试代码,模组,以及安装脚本. 由于编写一个Python文件可以作为一个模块,一个带__init__.py的目录算一个包. ...
- error MSB3073 解决办法
发现拷贝命令编译错误,查看输出列表发现时无法找到相应的路径. 1.顺着这个思路第一个想到的是中文路径的问题,先修改了盘符的中文名称,发现还是无法解决具体的问题. 2.后来反复查阅网上的资料,发现帮助并 ...
- TVTK库的安装
1.在网址为:http://www.lfd.uci.edu/~gohlke/pythonlibs/ 里下载以下内容: VTK-7.1.1-cp36-cp36m-win_amd64.whlnumpy-1 ...