如何获得UnsafeMutableRawPointer的值?

时间:2016-11-13 02:05:52

标签: ios swift swift3

我正在尝试获取UnsafeMutableRawPointer指向的地址,但我无法这样做。我也是Swift的新手,所以我可能会遗漏某些东西或完全错误。我希望将原始值转换为CChar。

enter image description here

2 个答案:

答案 0 :(得分:4)

对路人的注意:我的大部分答案都没有意义,因为它没有回答上面的初始问题,而是回答chat中出现的问题。 OP。

花了我几个小时,但是现在我学会了一些装配,我可以回答一些问题。

  1. CChar字面意思是C Char。它代表char类型C。它是typealiasInt8。这是一个字节。您不能像指针类型一样使用它,因为它们是8个字节(在64位计算机上)。

  2. 您不需要所有这些UnsafeMutableRawPointer样板,并且当然不需要访问其原始值。您可以直接在需要指针的位置传递数组。

      

    当一个函数声明为接受UnsafePointer参数时,它可以接受以下任何一个:...

         
        
    • 一个[Type]值,作为指向数组开头的指针传递。
    •   
    来自Interacting with C APIs - pointers

  3. 您遇到的问题是0x8(%rdi)的变异似乎没有反映在Swift方面。这里的问题是你写的是8字节的偏移量,但是print(a.load(as: void_star.self))正在读取第一个字节。你正在读一个你从未修改过的字节。

  4. 我做了一些进一步的探索。这是我冒险中的战利品:

    exampleSwift.swift:

    @_silgen_name("incrementByValue")
        func incrementByValue(_: Int64)
    
    @_silgen_name("incrementByReference")
        func incrementByReference(_: inout Int64)
    
    @_silgen_name("return1234")
        func return1234() -> Int64
    
    @_silgen_name("incrementElements")
        func incrementElements(of _: UnsafeRawPointer, count _: Int)
    
    var a: Int64 = 100
    print("\"a\" before \"incrementByValue(a)\": \(a)")
    incrementByValue(a)
    print("\"a\" after \"incrementByValue(a)\": \(a)\n")
    
    var b: Int64 = 200
    print("\"b\" before \"incrementByValue(b)\": \(b)")
    incrementByReference(&b)
    print("\"b\" after \"incrementByValue(b)\": \(b)\n")
    
    print("return1234() returned: \(return1234())\n")
    
    var array: [Int64] = Array(0...5)
    
    print("\"array\" before incrementElements(of: array, count: array.count): \n\t\(array)")
    incrementElements(of: array, count: array.count)
    print("\"array\" after incrementElements(of: array, count: array.count): \n\t\(array)\n")
    

    exampleASM.s:

    .text
    
    .globl _incrementByValue
    .globl _incrementByReference
    .globl _return1234
    .globl _incrementElements
    
    // A test routine that demonstrates operating on a value
    _incrementByValue:
        // %rdi contains a copy of the argument passed in.
        // Changes here won't be reflected back in Swift
        incq %rdi
        ret
    
    // A test routine that demonstrates operating on a reference
    _incrementByReference:
        // %rdi contains a reference tp the argument passed in.
        // Changes to the reference itself won't be reflected back in Swift,
        // but changes to the referenced memory will.
        incq (%rdi)
        ret
    
    // A test routine that demonstrates the use of %rax for returning a value
    _return1234:
        movq $1234, %rax    // return value is in rax
        ret
    
    //A test routine that demonstrates operating on an array
    _incrementElements:
        // %rdi: Pointer to first of n Int64 elements
        // %rsi: the array count, n
    
        movq    %rsi, %rcx  // Set loop counter (%rcx) to n
        aLoop:
            incq    (%rdi)      // increment value pointer to by %rdi
            add     $8, %rdi    // advance pointer by 8 bytes
            loop    aLoop       // loop back to aLoop if rcx > 0
    
        ret
    

    编译,链接并运行:

    llvm-g++ -c exampleASM.s &&
    swiftc -c exampleSwift.swift &&
    ld exampleASM.o exampleSwift.o -o exampleBinary -force_load /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_macosx.a -framework CoreFoundation -macosx_version_min 10.12.0 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -lobjc -lSystem -arch x86_64 -L /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx -rpath /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx -no_objc_category_merging &&
    ./exampleBinary
    

    输出:

    "a" before "incrementByValue(a)": 100
    "a" after "incrementByValue(a)": 100
    
    "b" before "incrementByValue(b)": 200
    "b" after "incrementByValue(b)": 201
    
    return1234() returned: 1234
    
    "array" before incrementElements(of: array, count: array.count): 
        [0, 1, 2, 3, 4, 5]
    "array" after incrementElements(of: array, count: array.count): 
        [1, 2, 3, 4, 5, 6]
    

答案 1 :(得分:1)

将MutableRawPointer转换为object,我们使用fromOpaque api

/// Unsafely turns an opaque C pointer into an unmanaged class reference.
///
/// This operation does not change reference counts.
///
///     let str: CFString = Unmanaged.fromOpaque(ptr).takeUnretainedValue()
///
/// - Parameter value: An opaque C pointer.
/// - Returns: An unmanaged class reference to `value`.
public static func fromOpaque(_ value: UnsafeRawPointer) -> Unmanaged<Instance>

示例:

var info:UnsafeMutableRawPointer = ....
let obj = Unmanaged<$AnyObject>.fromOpaque(info).takeUnretainedValue()