如何获得UnsafeMutableRawPointer的价值?
我试图得到UnsafeMutableRawPointer指向的地址,但我无法这样做。 我也是Swift的新手,所以我可能会错过一些东西或者完全错误。 最好我想把原始价值投入到CChar。
给路人的提示:我的答案大部分都没有意义,因为它不回答上面的问题,而是与OP 聊天中出现的问题。
花了我几个小时,但现在我已经学会了一些集会,我可以回答一些问题。
-
CChar
是C Char
…从字面上。 它表示C
的char
types。 这是typealias
的一个Int8
。 这是一个字节。 你不能像指针types那样使用它,因为它们是8个字节(在64位机器上)。 -
你不需要所有的这个
UnsafeMutableRawPointer
样板,你当然不需要访问它的原始值。 你可以直接在需要指针的地方传递数组。当一个函数被声明为采用UnsafePointer参数时,它可以接受以下任何一个:…
- 一个[Type]值,作为指针传递给数组的开始。
从与C API交互 – 指针 。
-
你遇到的问题是你的突变
0x8(%rdi)
似乎没有反映在Swift方面。 这里的问题是你正在写8字节的偏移量,但是然后print(a.load(as: void_star.self))
正在读取第一个字节。 你正在读一个你从未修改过的字节。
我做了一些进一步的探索。 这里是我的冒险的战利品:
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]
将MutableRawPointer转换为对象,我们使用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()