Swift编程语言是一门灵活、简洁、安全而又强大的编程语言。其简洁性与安全性从它语法设计上就能看出。而它的高效性从它可以提供针对硬件底层进行编程的特性就能看出。尤其是从Swift 2.x中,其指针类型的使用变得更加灵活,甚至可以直接将一个整数作为地址,使得单纯通过Swift本身即可访问MMR寄存器。不过本博文将描述它另一个非常棒的特性——即与C API几乎完美的兼容!
Swift编程语言与C语言的交互同Java、C#还不太一样,由于Swift的运行时非常小,它基本用于作为静态编译的编程语言进行使用,因此最终可以直接生成二进制目标文件与其他编程语言得到的二进制目标文件进行连接。所以它天生就能非常自然地与C语言、Objective-C进行交互使用。关于Swift与C语言指针类型的对应表可参考Apple官方的《Using Swift with Cocoa and Objective-C》文档。
Swift 3.0中引入了UnsafeRawPointer对应于C语言的const void *类型;UnsafeMutableRawPointer对应于void*类型,然后为它提供了显式转换为指向其他类型的指针对象的方法——assumingMemoryBound(to:)。对于指向不同对象类型的指针类型转换提供了withMemoryRebound(to:capacity:_:)方法。这些都可以参考此博文:http://blog.csdn.net/zenny_chen/article/details/53455940。本博文主要将介绍对于更复杂的多级指针类型,在Swift编程语言中如何体现;倘若我们要将一个Swift函数暴露给C语言使用,涉及到指针类型的话该如何判断。
我们先举一些例子,这里提供了TestPtr1道TestPtr5这5个函数,参数为一个指针对象,这些函数的形参类型由简单到复杂依次推进,所以我们可以更清晰地做类型分析。
首先是Swift与C桥接的头文件内容:
extern void TestPtr1(int * _Nonnull);
extern void TestPtr2(const int* _Nonnull);
extern void TestPtr3(int * _Nonnull * _Nonnull);
extern void TestPtr4(const int * _Nonnull * _Nonnull);
extern void TestPtr5(int const * _Nonnull const * _Nonnull);
上述函数原型声明中,为了简化指针类型的讨论,我们都将它们声明为_Nonnull属性。然后我们看看下面的C源文件对这些函数的实现:
#include
static int s = 100;
void TestPtr1(int *p)
{
*p += 10;
printf("This is: %s\n", __func__);
}
void TestPtr2(const int *p)
{
printf("This is: %s, *p = %d\n", __func__, *p);
}
void TestPtr3(int **pp)
{
*pp = &s;
printf("This is: %s\n", __func__);
}
void TestPtr4(const int **pp)
{
*pp = &s;
printf("This is: %s\n", __func__);
}
void TestPtr5(int const * const *pp)
{
printf("This is: %s, **pp = %d\n", __func__, **pp);
}
上述函数的实现都非常简单。因为我们主要关心的指针类型到Swift中所对应的类型。此外,我们可以看到函数形参从p到pp,类型由简单到复杂。
好!下面我们就来看看Swift源文件内容:
var a: Int32 = 1
// TestPtr1的类型为:(UnsafeMutablePointer) -> Void
TestPtr1(&a)
// TestPtr2的类型为:(UnsafePointer) -> Void
TestPtr2(&a)
// 这里制作一个指向变量a的指针变量
var aptr = withUnsafeMutablePointer(to: &a) {
return $0
}
// TestPtr3的类型为:(UnsafeMutablePointer>) -> Void
TestPtr3(&aptr)
// 我们这里可以看到,aptr已经被间接修改了,此时它指向了C源文件中定义的静态变量s的地址
print("aptr's content: \(aptr.pointee)")
// 我们这里通过aptr对它所指向的静态变量s做间接修改
aptr.pointee += 100
// 我们这里制作一个指向变量a的指针常量
var cptr = withUnsafePointer(to: &a) {
return $0
}
// TestPtr4的类型为:(UnsafeMutablePointer>) -> Void
TestPtr4(&cptr)
// 我们这里可以看到,cptr也被间接修改,指向了C源文件中的静态变量s的地址。
// 同时,我们也可以看到,静态变量s的值变成了200
print("cptr's content: \(cptr[0])")
// TestPtr5的类型为:(UnsafePointer>) -> Void
TestPtr5(&cptr)
通过强大的Xcode开发环境,它所提供的代码智能感知,我们只要输入某个函数名,那么其参数类型就会被自动展现出来,十分方便!
那么如果我们要实现一个Swift函数,其对应的C语言的指针类型该如何判定呢?其实规则非常简单!下面我将为大家介绍对应方法。
1、首先,在Swift中,一个变量是用var声明的,它对应到C语言中就是类型名,这里用Type表示。而一个常量是用let声明的,对应到C语言中用const Type表示。
2、Swift中引入了UnsafeMutablePointer
3、Swift中引入了UnsafePointer
好了,下面我们将根据上述三种类型的对应关系扩展到多级指针的类型对应法则上。首先,对于UnsafeMutablePointer< UnsafeMutablePointer
而对于UnsafeMutablePointer< UnsafePointer
而对于UnsafePointer< UnsafeMutablePointer
最后,UnsafePointer< UnsafePointer