如何获得 UnsafeMutableRawPointer 的值? [英] How to get value of UnsafeMutableRawPointer?

查看:27
本文介绍了如何获得 UnsafeMutableRawPointer 的值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to get the address that is pointed to by UnsafeMutableRawPointer, but I'm unable to do so. I'm also new to Swift so I might be missing something or doing it completely wrong. Preferably I would like to cast the raw value into a CChar.

推荐答案

路人注意:我的大部分回答没有意义,因为它没有回答上面最初的问题,而是在与 OP 的聊天中出现的问题.

Note to passers-by: much of my answer won't make sense, as it doesn't answer the initial question above, but rather the question(s) that arose in the chat with OP.

花了我几个小时,但现在我已经学会了一些组装,我可以回答一些问题了.

Took me a few hours, but now that I've learned some assembly, I can answer some questions.

  1. CChar 是一个 C Char ... 字面意思.它表示Cchar 类型.它是Int8typealias.它是一个字节.你不能像指针类型一样使用它,因为它们是 8 个字节(在 64 位机器上).

  1. CChar is a C Char ... literally. It represents the char type of C. It's a typealias to Int8. It's a single byte. You can't use this like a pointer type, as those are 8 bytes (on 64 bit machines).

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

You don't need all this UnsafeMutableRawPointer boilerplate, and you certainly don''t need to access its raw value. You can pass arrays directly where pointers are expected.

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

When a function is declared as taking an UnsafePointer argument, it can accept any of the following: ...

  • 一个 [Type] 值,作为指向数组开头的指针传递.

来自 与 C API 交互 - 指针.

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

You were experiencing issues were your mutation of 0x8(%rdi) did not seem to be reflected on the Swift side. The issue here is that you're writing at an offset of 8 bytes, but then print(a.load(as: void_star.self)) is reading the first byte. You're reading a byte you never modified.

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

I did some further exploration. Here's the loot from my adventure:

@_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]

这篇关于如何获得 UnsafeMutableRawPointer 的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆