Swift中對C語言接口緩存的使用以及數組、字符串轉為指針類型的方法


由於Swift編程語言屬於上層編程語言,而Swift中由於為了低層的高性能計算接口,所以往往需要C語言中的指針類型,由此,在Swift編程語言剛誕生的時候就有了UnsafePointer與UnsafeMutablePointer類型,分別對應為const Type*類型與Type *類型。

而在Swift編程語言中,由於一般數組(Array)對象都無法直接用於C語言中含有指針類型的函數參數(比如:void*),所以往往需要將數組轉為指針類型,此外也需要將數組中元素內容存放到連續的存儲空間。此外,Swift中的字符串對象都是String結構體對象,因此也需要將它們轉換為C語言中const char *類型相兼容的類型,因此這里將給大家介紹一些比較簡便、且純Swift接口的使用方法,而不是借助於Objective-C的Foundation庫。

/**
 此函數用於將一個數組(Array)的首個元素的值做加1操作
 - parameters:
    - p: inout [Int]類型,傳入的數組對象首地址
 - returns: Void
*/ func test(inout p: [Int]) {
    p[0] += 1
}

class ViewController: NSViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        var a = 0
        
        // 下面使用UnsafeMutablePointer自帶的alloc類方法分配10個Int元素的存儲空間
        // 這個方法其實應該就是對malloc函數的封裝了,用於外部的C接口十分有用
        let buf = UnsafeMutablePointer<Int>.alloc(10)
        let dst = UnsafeMutablePointer<Int>.alloc(10)
        
        // 分別對buf與dst存儲空間進行初始化賦值
        for i in 0 ..< 10 {
            buf[i] = i
            dst[i] = 0
        }
        
        // 使用assignBackwardFrom將buf存儲空間中后5個元素拷貝到dst存儲空間的前5個元素中
        dst.assignBackwardFrom(buf.advancedBy(5), count: 5)
        
        // 用Array分配一個10個Int元素的數組對象arr
        var arr = [Int](count: 10, repeatedValue: 0)
        
        // 將dst中的所有元素拷貝到arr中
        for i in 0 ..< 10 {
            arr[i] = dst[i]
        }
        print(arr)
        
        // 釋放buf與dst。注意,這里必須用dealloc來釋放,且里面的參數也要與alloc的參數對應!
        // 不釋放會引發內存泄漏
        buf.dealloc(10)
        dst.dealloc(10)
        
        // arr數組對象指向另一個[1, 2, 3]數組字面量構成的Array對象
        arr = [1, 2, 3]
        
        // 調用test函數,使得arr的第一個元素的值加1
        test(&arr)
        print("arr = \(arr)")
        
        // 這里使用Array的withUnsafeMutableBufferPointer方法將數組元素內容轉為
        // 指向一個連續存儲空間的首地址。
        // 所以p的類型為:UnsafeMutablePointer<Int>
        let p = arr.withUnsafeMutableBufferPointer() {
            // 這里,形參是一個含有一個UnsafeMutableBufferPointer的形參,
            // 返回類型為UnsafeMutablePointer的函數類型。
            (inout buffer: UnsafeMutableBufferPointer<Int>) -> UnsafeMutablePointer<Int> in
            return buffer.baseAddress
        }
        
        a = 0
        
        // 我們先查看原先數組對象中的元素內容
        for i in 0 ..< 3 {
            a += p[i]
        }
        print("a = \(a)")
        
        // 我們通過p指針對象對數組arr的內容進行修改
        p[0] -= 1
        p[1] += 1
        p[2] += 2
        
        // 然后打印出修改后的arr數組對象中的元素內容
        print("arr is: \(arr)")
        
        // 這里用nulTerminatedUTF8方法先轉為ContiguousArray<CodeUnit>對象類型,
        // 其中,CodeUnit是UInt8類型。
        // 然后用withUnsafeBufferPointer轉為UnsafePointer<CChar>類型
        let cstr = "abcd".nulTerminatedUTF8.withUnsafeBufferPointer() {
            return UnsafePointer<CChar>($0.baseAddress)
        }
        
        // 這里再將剛才生成的UnsafePointer<CChar>類型的C格式字符串轉回String對象
        let string = String.fromCString(cstr)!
        print("string is: \(string)")
    }
}

 

上述代碼中,UnsafeMutablePointer的alloc方法也是個很不錯的方法,這個方法應該是直接對C語言標准庫malloc的封裝,可以使得我們方便地在Swift中分配連續的存儲空間,比如對於像圖像處理、矩陣計算等算法尤為實用。當然,如果我們的邏輯主要用Array來處理,然后再交給底層的C語言接口做高性能計算,那么也可以使用數組對象轉連續存儲空間withUnsafeBufferPointer方法,這種處理方式在網絡數據通信中也比較實用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM