答案 0 :(得分:4)
对路人的注意:我的大部分答案都没有意义,因为它没有回答上面的初始问题,而是回答chat中出现的问题。 OP。
花了我几个小时,但是现在我学会了一些装配,我可以回答一些问题。
CChar
字面意思是C Char
。它代表char
类型C
。它是typealias
到Int8
。这是一个字节。您不能像指针类型一样使用它,因为它们是8个字节(在64位计算机上)。
您不需要所有这些UnsafeMutableRawPointer
样板,并且当然不需要访问其原始值。您可以直接在需要指针的位置传递数组。
来自Interacting with C APIs - pointers的当一个函数声明为接受UnsafePointer参数时,它可以接受以下任何一个:...
- 一个[Type]值,作为指向数组开头的指针传递。
。
您遇到的问题是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]
答案 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()