如何运用Swift与C语言交互编程,建议收藏!

作为一种可与 Objective-C 相互调用的语言,Swift 也具有一些与 C 语言的类型和特性,如果你的代码有需要,Swift 也提供了和常见的 C 代码结构混合编程的编程方式。 ![](https://upload-images.jianshu.io/upload_images/26131404-57c5e7726e5b0f2c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ## 基本数据类型 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 | ## 枚举 >作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS开发交流群:[130 595 548](https://jq.qq.com/?_wv=1027&k=L3kztZno),不管你是小白还是大牛都欢迎入驻 ,让我们一起进步,共同发展!(群内会免费提供一些群主收藏的免费学习书籍资料以及整理好的几百道面试题和答案文档!) Swift 引进了用宏NS_ENUM来标记的任何 C 风格的枚举类型。这意味着无论枚举值是在系统框架还是在自定义的代码中定义的,当他们导入到 Swift 时,他们的前缀名称将被截断。例如,看这个 Objective-C 枚举: ``` 1. //Objective-C 2. typedef NS_ENUM(NSInteger, UITableViewCellStyle) { 3. UITableViewCellStyleDefault, 4. UITableViewCellStyleValue1, 5. UITableViewCellStyleValue2, 6. UITableViewCellStyleSubtitle 7. }; ``` 在 Swift 中这样来实现: ``` 1. //Swift 2. enum UITableViewCellStyle: Int { 3. case Default 4. case Value1 5. case Value2 6. case Subtitle 7. } ``` 当您需要指向一个枚举值时,使用以点(.)开头的枚举名称: ``` 1. //Swift 2. let cellStyle: UITableViewCellStyle = .Default ``` Swift 也引进了标有NS_OPTIONS宏选项。而选项的行为类似于引进的枚举,选项还可以支持一些位操作,如 &,| 和 ~。在 Objective-C 中,你用一个空的选项设置标示恒为零(0)。在 Swift 中,使用 nil代表没有任何选项。 ## 指针 Swift 尽可能避免让您直接访问指针。然而,当您需要直接操作内存的时候,Swift 也为您提供了多种指针类型。下面的表使用 Type 作为占位符类型名称来表示语法的映射。 对于参数,使用以下映射: | C 句法 | Swift 句法 | | --- | --- | | const void * | CConstVoidPointer | | void * | CMutableVoidPointer | | const Type * | CConstPointer | | Type * | CMutablePointer | 对于返回类型,变量和参数类型的多层次指针,使用以下映射: | C 句法 | Swift 句法 | | --- | --- | | void * | COpaquePointer | | Type * | UnsafePointer | 对于类(class)类型,使用以下映射: | C 句法 | Swift 句法 | | --- | --- | | Type * const * | CConstPointer | | Type * __strong * | CMutablePointer | | Type ** | AutoreleasingUnsafePointer | #### C 可变指针 当一个函数被声明为接受CMutablePointer参数时,这个函数可以接受下列任何一个类型作为参数: * nil,作为空指针传入 * 一个CMutablePointer类型的值 * 一个操作数是 Type 类型的左值的输入输出表达式,作为这个左值的内存地址传入 * 一个输入输出 Type[] 值,作为一个数组的起始指针传入,并且它的生命周期将在这个调用期间被延长 如果您像这样声明了一个函数: ``` 1. //Swift 2. func takesAMutablePointer(x: CMutablePointer) { /*...*/ } ``` 那么您可以使用以下任何一种方式来调用这个函数: ``` 1. //Swift 2. var x: Float = 0.0 3. var p: CMutablePointer = nil 4. var a: Float[] = [1.0, 2.0, 3.0] 6. takesAMutablePointer(nil) 7. takesAMutablePointer(p) 8. takesAMutablePointer(&x) 9. takesAMutablePointer(&a) ``` 当函数被声明使用一个CMutableVoidPointer参数,那么这个函数接受任何和CMutablePointer相似类型的Type操作数。 如果您这样定义了一个函数: ``` 1. //Swift 2. func takesAMutableVoidPointer(x: CMutableVoidPointer) { /* ... */ } ``` 那么您可以使用以下任何一种方式来调用这个函数: ``` //Swift var x: Float = 0.0, y: Int = 0 var p: CMutablePointer = nil, q: CMutablePointer = 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 常指针 当一个函数被声明为接受CConstPointer参数时,这个函数可以接受下列任何一个类型作为参数: * nil,作为空指针传入 * 一个CMutablePointer, CMutableVoidPointer, CConstPointer, CConstVoidPointer, 或者在必要情况下转换成CConstPointer的AutoreleasingUnsafePointer值 * 一个操作数是 Type 类型的左值的输入输出表达式,作为这个左值的内存地址传入 * 一个Type[]数组值,作为一个数组的起始指针传入,并且它的生命周期将在这个调用期间被延长 如果您这样定义了一个函数: ``` 1. //Swift 2. func takesAConstPointer(x: CConstPointer) { /*...*/ } ``` 那么您可以使用以下任何一种方式来调用这个函数: ``` 1. //Swift 2. var x: Float = 0.0 3. var p: CConstPointer = nil 5. takesAConstPointer(nil) 6. takesAConstPointer(p) 7. takesAConstPointer(&x) 8. takesAConstPointer([1.0, 2.0, 3.0]) ``` 当函数被声明使用一个CConstVoidPointer参数,那么这个函数接受任何和CConstPointer 相似类型的Type操作数。  如果您这样定义了一个函数: 1. //Swift  2. func takesAConstVoidPointer(x: CConstVoidPointer) { /* ... */ } 那么您可以使用以下任何一种方式来调用这个函数: ``` 1. //Swift 2. var x: Float = 0.0, y: Int = 0 3. var p: CConstPointer = nil, q: CConstPointer = nil 5. takesAConstVoidPointer(nil) 6. takesAConstVoidPointer(p) 7. takesAConstVoidPointer(q) 8. takesAConstVoidPointer(&x) 9. takesAConstVoidPointer(&y) 10. takesAConstVoidPointer([1.0, 2.0, 3.0]) 11. takesAConstVoidPointer([1, 2, 3]) ``` #### 自动释放不安全指针 当一个函数被声明为接受AutoreleasingUnsafePointer参数时,这个函数可以接受下列任何一个类型作为参数: * nil,作为空指针传入 * 一个AutoreleasingUnsafePointer值 * 其操作数是原始的,复制到一个临时的没有所有者的缓冲区的一个输入输出表达式,该缓冲区的地址传递给调用,并返回时,缓冲区中的值加载,保存,并重新分配到操作数。 注意:这个列表没有包含数组。 如果您这样定义了一个函数: ``` 1. //Swift 2. func takesAnAutoreleasingPointer(x: AutoreleasingUnsafePointer<NSDate?>) { /* ... */ } ``` 那么您可以使用以下任何一种方式来调用这个函数: ``` 1. //Swift 2. var x: NSDate? = nil 3. var p: AutoreleasingUnsafePointer<NSDate?> = nil 4.  5. takesAnAutoreleasingPointer(nil) 6. takesAnAutoreleasingPointer(p) 7. takesAnAutoreleasingPointer(&x) ``` 注意:C 语言函数指针没有被 Swift 引进。 ## 全局常量 在 C 和 Objective-C 语言源文件中定义的全局常量会自动地被 Swift 编译引进并做为 Swift 的全局常量。 ## 预处理指令 Swift 编译器不包含预处理器。取而代之的是,它充分利用了编译时属性,生成配置,和语言特性来完成相同的功能。因此,Swift 没有引进预处理指令。 #### 简单宏 在 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 中使用的复杂宏在 Swift 中并没有与之对应的定义。复杂宏是那些不用来定义常量的宏,而是用来定义包含小括号(),函数的宏。您在 C 和 Objective-C 使用复杂的宏是用来避免类型检查的限制和相同代码的重复劳动。然而,宏也会产生Bug和重构的困难。在 Swift 中你可以直接使用函数和泛型来达到同样的效果。因此,在 C 和 Objective-C 源文件中定义的复杂宏在 Swift 是不能使用的。 #### 编译配置 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。 一个简单的条件编译需要以下代码格式: ``` 1. #if build configuration 2. statements 3. #else 4. statements 5. #endif ``` 一个由零个或多个有效的 Swift 语句声明的statements,可以包括表达式,语句和控制流语句。您可以添加额外的构建配置要求,条件编译说明用 && 和 | | 操作符以及 ! 操作符,添加条件控制块用 #elseif: ``` 1. #if build configuration && !build configuration 2. statements 3. #elseif build configuration 4. statements 5. #else 6. statements 7. #endif ``` 与 C 语言编译器的条件编译相反,Swift 条件编译语句必须完全是自包含和语法有效的代码块。这是因为 Swift 代码即使没有被编译,也要全部进行语法检查。

原文地址:https://blog.51cto.com/u_15146321/2954571

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘贴.待开发的功能:1.支持自动生成约束2.开发设置页面3.做一个浏览器插件,支持不需要下载整个工程,可即时操作当前蓝湖浏览页面4.支持Flutter语言模板生成5.支持更多平台,如Sketch等6.支持用户自定义语言模板
现实生活中,我们听到的声音都是时间连续的,我们称为这种信号叫模拟信号。模拟信号需要进行数字化以后才能在计算机中使用。目前我们在计算机上进行音频播放都需要依赖于音频文件。那么音频文件如何生成的呢?音频文件的生成过程是将声音信息采样、量化和编码产生的数字信号的过程,我们人耳所能听到的声音频率范围为(20Hz~20KHz),因此音频文件格式的最大带宽是20KHZ。根据奈奎斯特的理论,音频文件的采样率一般在40~50KHZ之间。奈奎斯特采样定律,又称香农采样定律。...............
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿遍又亿遍,久久不能离开!看着小仙紫姐姐的蹦迪视频,除了一键三连还能做什么?突发奇想,能不能把舞蹈视频转成代码舞呢?说干就干,今天就手把手教大家如何把跳舞视频转成代码舞,跟着仙女姐姐一起蹦起来~视频来源:【紫颜】见过仙女蹦迪吗 【千盏】一、核心功能设计总体来说,我们需要分为以下几步完成:从B站上把小姐姐的视频下载下来对视频进行截取GIF,把截取的GIF通过ASCII Animator进行ASCII字符转换把转换的字符gif根据每
【Android App】实战项目之仿抖音的短视频分享App(附源码和演示视频 超详细必看)
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至2022年4月底。我已经将这篇博客的内容写为论文,上传至arxiv:https://arxiv.org/pdf/2204.10160.pdf欢迎大家指出我论文中的问题,特别是语法与用词问题在github上,我也上传了完整的项目:https://github.com/Whiffe/Custom-ava-dataset_Custom-Spatio-Temporally-Action-Video-Dataset关于自定义ava数据集,也是后台
因为我既对接过session、cookie,也对接过JWT,今年因为工作需要也对接了gtoken的2个版本,对这方面的理解还算深入。尤其是看到官方文档评论区又小伙伴表示看不懂,所以做了这期视频内容出来:视频在这里:本期内容对应B站的开源视频因为涉及的知识点比较多,视频内容比较长。如果你觉得看视频浪费时间,可以直接阅读源码:goframe v2版本集成gtokengoframe v1版本集成gtokengoframe v2版本集成jwtgoframe v2版本session登录官方调用示例文档jwt和sess
【Android App】实战项目之仿微信的私信和群聊App(附源码和演示视频 超详细必看)
用Android Studio的VideoView组件实现简单的本地视频播放器。本文将讲解如何使用Android视频播放器VideoView组件来播放本地视频和网络视频,实现起来还是比较简单的。VideoView组件的作用与ImageView类似,只是ImageView用于显示图片,VideoView用于播放视频。...
采用MATLAB对正弦信号,语音信号进行生成、采样和内插恢复,利用MATLAB工具箱对混杂噪声的音频信号进行滤波
随着移动互联网、云端存储等技术的快速发展,包含丰富信息的音频数据呈现几何级速率增长。这些海量数据在为人工分析带来困难的同时,也为音频认知、创新学习研究提供了数据基础。在本节中,我们通过构建生成模型来生成音频序列文件,从而进一步加深对序列数据处理问题的了解。
基于yolov5+deepsort+slowfast算法的视频实时行为检测。1. yolov5实现目标检测,确定目标坐标 2. deepsort实现目标跟踪,持续标注目标坐标 3. slowfast实现动作识别,并给出置信率 4. 用框持续框住目标,并将动作类别以及置信度显示在框上
数字电子钟设计本文主要完成数字电子钟的以下功能1、计时功能(24小时)2、秒表功能(一个按键实现开始暂停,另一个按键实现清零功能)3、闹钟功能(设置闹钟以及到时响10秒)4、校时功能5、其他功能(清零、加速、星期、八位数码管显示等)前排提示:前面几篇文章介绍过的内容就不详细介绍了,可以看我专栏的前几篇文章。PS.工程文件放在最后面总体设计本次设计主要是在前一篇文章 数字电子钟基本功能的实现 的基础上改编而成的,主要结构不变,分频器将50MHz分为较低的频率备用;dig_select
1.进入官网下载OBS stdioOpen Broadcaster Software | OBS (obsproject.com)2.下载一个插件,拓展OBS的虚拟摄像头功能链接:OBS 虚拟摄像头插件.zip_免费高速下载|百度网盘-分享无限制 (baidu.com)提取码:6656--来自百度网盘超级会员V1的分享**注意**该插件必须下载但OBS的根目录(应该是自动匹配了的)3.打开OBS,选中虚拟摄像头选择启用在底部添加一段视频录制选择下面,进行录制.
Meta公司在9月29日首次推出一款人工智能系统模型:Make-A-Video,可以从给定的文字提示生成短视频。基于**文本到图像生成技术的最新进展**,该技术旨在实现文本到视频的生成,可以仅用几个单词或几行文本生成异想天开、独一无二的视频,将无限的想象力带入生活
音频信号叠加噪声及滤波一、前言二、信号分析及加噪三、滤波去噪四、总结一、前言之前一直对硬件上的内容比较关注,但是可能是因为硬件方面的东西可能真的是比较杂,而且需要渗透的东西太多了,所以学习进展比较缓慢。因为也很少有单纯的硬件学习研究,总是会伴随着各种理论需要硬件做支撑,所以还是想要慢慢接触理论学习。但是之前总找不到切入点,不知道从哪里开始,就一直拖着。最近稍微接触了一点信号处理,就用这个当作切入点,开始接触理论学习。二、信号分析及加噪信号处理选用了matlab做工具,选了一个最简单的语音信号处理方
腾讯云 TRTC 实时音视频服务体验,从认识 TRTC 到 TRTC 的开发实践,Demo 演示& IM 服务搭建。
音乐音频分类技术能够基于音乐内容为音乐添加类别标签,在音乐资源的高效组织、检索和推荐等相关方面的研究和应用具有重要意义。传统的音乐分类方法大量使用了人工设计的声学特征,特征的设计需要音乐领域的知识,不同分类任务的特征往往并不通用。深度学习的出现给更好地解决音乐分类问题提供了新的思路,本文对基于深度学习的音乐音频分类方法进行了研究。首先将音乐的音频信号转换成声谱作为统一表示,避免了手工选取特征存在的问题,然后基于一维卷积构建了一种音乐分类模型。
C++知识精讲16 | 井字棋游戏(配资源+视频)【赋源码,双人对战】
本文主要讲解如何在Java中,使用FFmpeg进行视频的帧读取,并最终合并成Gif动态图。
在本篇博文中,我们谈及了 Swift 中 some、any 关键字以及主关联类型(primary associated types)的前世今生,并由浅及深用简明的示例向大家讲解了它们之间的奥秘玄机。