美文网首页
004-Swift进阶-指针-metadata结构

004-Swift进阶-指针-metadata结构

作者: Stronger_J | 来源:发表于2020-12-17 10:58 被阅读0次

    一、介绍

    Swift中的指针分为两类, typed pointer 指定数据类型指针, raw pointer 未指定数据类型的指针 (原⽣指针)
    raw pointer 在 Swift 中的表示是 UnsafeRawPointer
    tyepd pointer 在 Swift 中的表示是 UnsafePointer<T>


    image.png

    二、使用

    1、原始指针:RawPionter的使用

    /**
     RawPionter的使用
     */
    //1、分配32字节的内存空间大小
    let p = UnsafeMutableRawPointer.allocate(byteCount: 32, alignment: 8)
    //2、advanced代表当前 p 前进的步长,对于 RawPointer 来说,我们需要移动的是当前存储值得内存大小即,MemoryLayout.stride
    //3、storeBytes: 这里就是存储我们当前的数据,这里需要制定我们当前数据的类型
    for i in 0..<4{
        p.advanced(by: i * 8).storeBytes(of: i + 1, as: Int.self)
    }
    //4、load顾明思义是加载,fromBytesOffe:是相对于我们当前 p 的首地址的偏移
    for i in 0..<4{
        let value = p.load(fromByteOffset: i * 8, as: Int.self)
        print("index\(i),value:\(value)")
    }
    p.deallocate()
    

    2、Type pointer :确定类型的指针

    • 第一种
    //如何获取 age 变量的地址
    var age = 10
    //1、通过Swift提供的简写的API,这里注意当前尾随闭包的写法
    let p = withUnsafePointer(to: &age){$0}
    print(p.pointee)
    
    //2、withUnsafePointer的返回值是 unSafePointer,意味着我们不能直接修改值
    var b = withUnsafePointer(to: &age){ prt in
        prt.pointee += 12
    }
    
    //3、如果我们想要直接修改当前Pointer.pointee的值,那么使用withUnsafeMutablePointer
    withUnsafeMutablePointer(to: &age){ptr  in
        ptr.pointee += 10
    }
    print(age)
    
    • 第二种
    //1、capacity:容量大小,当前的大小为 1 * 8字节
    let ptr = UnsafeMutablePointer<Int>.allocate(capacity: 1)
    //2、初始化当前的UnsafeMutablePointer<Int> 指针
    ptr.initialize(to: age)
    //3、下面两个成对调用,管理内存
    ptr.deinitialize(count: 1)
    ptr.deallocate()
    

    3、多种方式访问类型指针

    class LJTest {
        var age = 18
        var name = "Swift"
        init() {
        }
        init(age: Int, name: String) {
            self.age = age
            self.name = name
        }
    }
    var t = LJTest()
    var t1 = LJTest(age: 100, name: "LJ")
    let ptr = UnsafeMutablePointer<LJTest>.allocate(capacity: 2)
    ptr.initialize(to: t)
    // 注意这里的advanced 其实就是当前要移动是i * 类型大小中的i
    ptr.advanced(by: 1).initialize(to: t1)
    
    print(MemoryLayout<LJTest>.size)
    print(MemoryLayout<LJTest>.stride)
    
    print("age : \(ptr[0].age), name : \(ptr[0].name)")
    print("age : \(ptr[1].age), name : \(ptr[1].name)")
    print("age : \(ptr.pointee.age), name : \(ptr.pointee.name)")
    print("age : \((ptr + 1).pointee.age), name : \((ptr + 1).pointee.name)")
    print("age : \(ptr.successor().pointee.age), name : \(ptr.successor().pointee.name)")
    
    ptr.deinitialize(count: 2)
    ptr.deallocate()
    

    4、绑定

    • withMemoryRebound : 临时更改内存绑定类型
    • bindMemory(to: Capacity:) : 更改内存绑定的类型,如果之前没有绑定,那么就是⾸次绑定;如果绑定过了,会被重新绑定为该类型。
    • assumingMemoryBound: 假定内存绑定,这⾥是告诉编译器:哥们我就是这种类型,你不要检查我 了。
    //练习demo,重构matedata
    class LJTest {
        var age = 18
        var name = "Swift"
    }
    struct HeapObject {
        var kind: UnsafeRawPointer
        var strongref: UInt32
        var unownedRef: UInt32
    }
    struct lj_swift_class {
        var kind: UnsafeRawPointer
        var superClass: UnsafeRawPointer
        var cachedata1: UnsafeRawPointer
        var cachedata2: UnsafeRawPointer
        var data: UnsafeRawPointer
        var flags: UInt32
        var instanceAddressOffset: UInt32
        var instanceSize: UInt32
        var flinstanceAlignMask: UInt16
        var reserved: UInt16
        var classSize: UInt32
        var classAddressOffset: UInt32
        var description: UnsafeRawPointer
    
    }
    
    var t = LJTest()
    let ptr = Unmanaged.passUnretained(t as AnyObject).toOpaque()
    let heapObjcet = ptr.bindMemory(to: HeapObject.self, capacity: 1)
    let metaPtr = heapObjcet.pointee.kind.bindMemory(to: lj_swift_class.self, capacity: 1)
    
    print(metaPtr.pointee)
    

    指针类型的转换

    var tul = (10, "a")
    func testPointer(_ p: UnsafePointer<String>){
        print(p)
    }
    withUnsafePointer(to: &tul) { (tulPtr: UnsafePointer<(Int, String)>) in
        print(tulPtr)
        let rePtr = UnsafeRawPointer(tulPtr).assumingMemoryBound(to: String.self)
        print(rePtr)
        testPointer(rePtr)
    }
    
    //获取结构体重参数的地址
    struct LJTest_Struct {
        var age = 18
        var name = "swift"
    }
    
    var t = LJTest_Struct()
    func testPointer(_ p: UnsafePointer<String>){
        let ptr = UnsafeMutableRawPointer(mutating: p)
        ptr.storeBytes(of: p.pointee + "_LJ", as: String.self)
        print(p)
    }
    withUnsafePointer(to: &t) { (ptr: UnsafePointer<LJTest_Struct>) in
        print(ptr)
        let rePtr = UnsafeRawPointer(ptr) + MemoryLayout<LJTest_Struct>.offset(of: \LJTest_Struct.name)!
        print(rePtr)
        testPointer(rePtr.assumingMemoryBound(to: String.self))
    }
    

    临时修改类型

    var age = 18
    let ptr = withUnsafePointer(to: &age){$0}
    func testPointer(_ p: UnsafePointer<UInt64>){
        print(p.pointee)
        let ptr = UnsafeMutablePointer(mutating: p)
        ptr.pointee += 100
        print(ptr.pointee)
    }
    ptr.withMemoryRebound(to: UInt64.self, capacity: 1) { (p: UnsafePointer<UInt64>) in
        testPointer(p)
    }
    

    相关文章

      网友评论

          本文标题:004-Swift进阶-指针-metadata结构

          本文链接:https://www.haomeiwen.com/subject/buoogktx.html