Swift与C指针交互

Objective-C和C API经常需要使用指针. 在设计上, Swift数据类型可以自然的与基于指针的Cocoa API一起工作, Swift自动处理几种常用的指针参数. 在本文中, 我们将看到C中的指针参数如何与Swift中的变量,数组,字符串一起工作.

指针作为输入/输出参数

C和Objective-C不支持多个返回值, 所以Cocoa API经常使用指针传递附加参数到函数. Swift允许把指针参数看成[inout]参数, 所以你可以用同样的&语法传递一个变量的引用作为指针. 例如: UIColor的getRed(_:green:blue:alpha:)方法使用4个CGFloat*指针来接受颜色的组合. 我们可以用&来得到这些值:

var r: CGFloat = , g:Float = , b:Float = , a:Float =
color.getRed(&r, green: &g, blue: &b, alpha: &a)

另一个经常使用的是NSError. 许多方法使用了NSError*参数来保存发生的错误. 例如: 我们列举目录里的内容使用NSFileManager的contentsOfDirectoryAtPath(_:error:)方法, 直接使用NSError?变量来保存可能的错误:

var maybeError:NSError?
if let contents = NSFileManager.defaultManager().contentsOfDirectoryAtPath("/usr/bin", error: &maybeError){
//内容处理
for i in contents{
println(i)
}
}else if let error = maybeError{
//错误处理
println(error.description)
}

安全起见, Swift要求变量在使用&前需要初始化. 因为它不知道被调用的方法是否在修改它之前会读取指针

数组指针

在C中数组与指针紧紧相连. 为方便使用基于数组的C API, Swift允许将Array作为指针. 不可修改数组可以直接当成常量指针, 可修改数组可以使用&操作符做为非常量指针(就和inout参数一样). 例如: 我们把两个数组 a 和 b 使用vDSP_vadd函数(Accelerte framework)相加, 把结果写到第三个数组 result 中:

  import Accelerate

  let a: [Float] = [, , , ]
let b: [Float] = [0.5, 0.25, 0.125, 0.0625]
var result: [Float] = [, , , ] vDSP_vadd(a, , b, , &result, , ) // result now contains [1.5, 2.25, 3.125, 4.0625]

字符串指针

C使用 const char*指针作为传递字符串的主要方式. Swift String可以作为const char*指针, 它会给函数传递一个 null结束, UTF-8编码的字符串指针. 例如, 我们可以直接给标准C和POSIX库函数传递字符串:

  puts("Hello from libc")
let fd = open("/tmp/scratch.txt", O_WRONLY|O_CREAT, 0o666) if fd < {
perror("could not open /tmp/scratch.txt")
} else {
let text = "Hello World"
write(fd, text, strlen(text))
close(fd)
}

指针参数转换的安全性
Swift尽可能让与C指针的交互方便并提供了一定的安全性, 因为C指针无处不在. 但是, 与C指针交互相对于Swift代码来说还是内存的不安全, 因此需要特别注意. 特别的:
* These conversions cannot safely be used if the callee saves the pointer value for use after it returns. The pointer that results from these conversions is only guaranteed to be valid for the duration of a call. Even if you pass the same variable, array, or string as multiple pointer arguments, you could receive a different pointer each time. An exception to this is global or static stored variables. You can safely use the address of a global variable as a persistent unique pointer value, e.g.: as a KVO context parameter.
* Array和String指针没有边界检查. C API不会扩大数组和字符串, 因此在调用前你需要为它分配足够的大小

如果上面的指南不满足你指针交互的需要, 或者你想手动控制指针参数, 你可以直接使用unsafe指针操作内存. 我们会在将来的文章中看到更多高级应用.

iOS: 学习笔记, Swift与C指针交互(译)的更多相关文章

  1. iOS: 学习笔记, Swift与Objective-C混用总结

    Swift与Objective-C交互总结 在Swift中使用Objective-C(简单) 在创建OjbC文件时, XCode会提示创建XXX-Bridging-Header.h文件, 创建之 在创 ...

  2. iOS: 学习笔记, Swift与Objective-C混用简明教程(转载)

    Swift与Objective-C混用简明教程 转载自:https://github.com/lifedim/SwiftCasts/tree/master/000_mix_swift_objc 我想很 ...

  3. iOS: 学习笔记, Swift名字空间

    在Swift中, 名字空间是用class(extension)嵌套来实现的, 下面用一个简单例子来进行展示 // // main.swift // SwiftNameSpace // // Creat ...

  4. iOS: 学习笔记, Swift运算符定义

    Swift操作符可以自行定义, 只需要加上简单的标志符即可. @infix 中置运算. 如+,-,*,/运算 @prefix 前置运算. 如- @postfix 后置运算. a++, a-- @ass ...

  5. iOS: 学习笔记, swift扩展

    // // YYExtension.swift // // Created by yao_yu on 14-7-18. // Copyright (c) 2014年 yao_yu. All right ...

  6. iOS: 学习笔记, Swift操作符定义

    Swift操作符能够自行定义, 仅仅须要加上简单的标志符就可以. @infix 中置运算. 如+,-,*,/运算 @prefix 前置运算. 如- @postfix 后置运算. a++, a-- @a ...

  7. IOS学习笔记48--一些常见的IOS知识点+面试题

      IOS学习笔记48--一些常见的IOS知识点+面试题   1.堆和栈什么区别? 答:管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制:对于堆来说,释放工作由程序员控制,容易产生memor ...

  8. iOS学习笔记-自定义过渡动画

    代码地址如下:http://www.demodashi.com/demo/11678.html 这篇笔记翻译自raywenderlick网站的过渡动画的一篇文章,原文用的swift,由于考虑到swif ...

  9. IOS学习笔记25—HTTP操作之ASIHTTPRequest

    IOS学习笔记25—HTTP操作之ASIHTTPRequest 分类: iOS2012-08-12 10:04 7734人阅读 评论(3) 收藏 举报 iosios5网络wrapper框架新浪微博 A ...

随机推荐

  1. typeof和instanceof 运算符

    instanceof运算符与typeof运算符相似,用于识别正在处理的对象的类型,但是在使用 typeof 运算符时采用引用类型存储值会出现一个问题. 无论引用的是什么类型的对象,它都返回 " ...

  2. SQLite 入门教程(四)增删改查,有讲究 (转)

    转于: SQLite 入门教程(四)增删改查,有讲究 一.插入数据 INSERT INTO 表(列...) VALUES(值...) 根据前面几篇的内容,我们可以很轻送的创建一个数据表,并向其中插入一 ...

  3. java中如何使正在运行中的线程退出

    终止线程的三种方法      有三种方法可以使终止线程.      1.  使用退出标志,使线程正常退出,也就是当run方法完成后线程终止.      2.  使用stop方法强行终止线程(这个方法不 ...

  4. 如何屏蔽Button setClickable与setEnabled

    今天想让按键暂时无效,满足一定条件下才可以被用户按到.最初以为是setClickable,谁知搞错了.请看手册: 复制代码代码如下: public void setClickable (boolean ...

  5. PowerShell自定义对象

    前面的性能高 使用[pscustomobject][ordered]强制类型转换 [pscustomobject][ordered]@{Name= 'Boe'Number = 1ID = 007} 使 ...

  6. Yet Another 10 Common Mistakes Java Developers Make When Writing SQL (You Won’t BELIEVE the Last One)--reference

    (Sorry for that click-bait heading. Couldn’t resist ;-) ) We’re on a mission. To teach you SQL. But ...

  7. Android 上使用 iconfont 的一种便捷方案

    最近在学习 AIOSO(Alibaba Internal Open Source Organization,即阿里巴巴内部开源组织) 的一个子项目MMCherryUI,这是一个流式布局,可以在运行时做 ...

  8. Eclipse下安装/配置Jrebel6.X

    Eclipse3.6+下安装/配置Jrebel6.X 1. 为什么要使用Jrebel 在日常开发过程中, 一旦修改配置/在类中增加静态变量/增加方法/修改方法名等情况, tomcat不会自动加载, 需 ...

  9. Linux重复执行上一条命令

    执行刚刚执行的一条命令: !! 执行最近一个以指定字符串开头的命令(比如man) !man !m 引用上一个命令的最后一个参数 !$ <ESC>, .

  10. php错误处理和异常处理

    PHP错误处理有两种:标准的错误处理和异常(OOP语法新出现的错误处理机制)