获取函数的地址[Swift 3.0]

时间:2016-07-31 19:51:22

标签: ios swift pointers memory

您可以使用AnyObject函数调用获取unsafeAdressOf(object:AnyObject) -> UnsafePointer<void>的地址,但如何获取函数的地址?例如

func foo(){print("hi")}
print(unsafeAdressOf(foo))

不起作用

1 个答案:

答案 0 :(得分:0)

不同的方法分派有不同的方法来获取Swift的函数指针。

这里是获取类的实例vtable方法指针的示例。

public func swift_getClassInstanceMethod(_ objc_class: AnyClass, methodIndex offset: Int) -> UnsafeMutablePointer<UnsafeMutableRawPointer>? {
    let classPointer = Unmanaged.passUnretained(objc_class as AnyObject).toOpaque()

    guard let outCount = malloc(MemoryLayout<UInt32>.size)?.assumingMemoryBound(to: UInt32.self) else { return nil }
    defer {
        free(outCount)
    }
    let _ = class_copyIvarList(objc_class, outCount)

    let cachePointer = classPointer.advanced(by: 0x50 + 32*Int(outCount.pointee))
    return cachePointer.advanced(by: offset*MemoryLayout<UnsafeMutableRawPointer>.size).assumingMemoryBound(to: UnsafeMutableRawPointer.self)
}

class B {
    var a: Int = 1
    var b: String?

    // vtable: 0
    init() {
    }

    // vtable: 1
    func bTest() {
        print("B test")
    }
}

let B_bTest_pointer = swift_getClassInstanceMethod(B.self, methodIndex: 1)

另一种间接获取方法指针的方法。

typealias NewSwiftNSLog = @convention(thin) (_ format: String, _ args: CVarArg...) -> Void

func newNSLog(_ format: String, _ args: CVarArg...) {
    print("hello world")
}

let nslog: NewSwiftNSLog = newNSLog
let nslogPointer = unsafeBitCast(nslog, to: UnsafeMutableRawPointer.self)

nslogPointer不是newNSLog函数指针,但是nslogPointer将调用newNSLog方法。