提醒路人:我的答案很多地方可能不太合理,因为它并没有回答上面的初始问题,而是回答了与OP的聊天中出现的问题。
花了我几个小时的时间,但现在我学会了一些汇编语言,可以回答一些问题。
CChar
是一个C Char
,字面意思就是表示C
的char
类型。它是Int8
的typealias
。它是一个单独的字节。你不能像指针类型那样使用它,因为这些指针在64位机器上有8个字节。
你不需要所有这些UnsafeMutableRawPointer
的样板代码,你当然也不需要访问它的原始值。你可以直接传递数组到期望指针的位置。
当一个函数被声明为接受一个UnsafePointer参数时,它可以接受以下任何一种:
- A [Type] value, which is passed as a pointer to the start of the array.
你遇到的问题是,你对0x8(%rdi)
的改变似乎没有在Swift端反映出来。这里的问题是,你正在写入8个字节的偏移量,但是print(a.load(as: void_star.self))
正在读取第一个字节。你正在读取一个你从未修改过的字节。
我进行了进一步的探索。这是我的冒险战利品:
@_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")
.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()
Int
做什么,而你不能用UnsafeMutableRawPointer
更安全、更表达的方式来完成吗? - Alexander