A few questions upfront:
are existentials of types cached and kept alive (a pointer to a newly created instance is always the same)?
we should be able to restore access to that existential instance from a pointer right?
Here is what I'm trying to do, but failing at:
protocol P {
static func foo()
}
struct ConcreteP: P {
static func foo() {
print("ConcreteP foo")
}
}
let existential: P.Type = ConcreteP.self
let identifier = ObjectIdentifier(existential)
let bits = UInt(bitPattern: identifier)
if let pointer = UnsafePointer<P.Type>(bitPattern: bits) {
print(pointer, String(bits, radix: 16), identifier, separator: "\n")
// THIS TRAPS! :(
// print(pointer.pointee)
}
I'm not that comfortable with the Unsafe*
API family, so any help is appreciated.
I figured out that ObjectIdentifier
is probably not what I wanted, but with other approach of creating the bits
from an UnsafePointer
leads me to a dead-end where I cannot re-create the existential from the bits as the original existential is deallocated.
If there is a good way of doing the latter, I'd appreciate the help.
Lantua
March 24, 2020, 12:00pm
3
If its lifetime is scoped, you can use withUnsafePointer
:
withUnsafePointer(to: existential) { pointer in
let bits = UInt(bitPattern: pointer)
if let pointer = UnsafePointer<P.Type>(bitPattern: bits) {
print(pointer)
print(pointer.pointee)
}
}
If it is long-lived, you need to do the allocation yourself:
let pointer = UnsafeMutablePointer<P.Type>.allocate(capacity: 1)
let bits = UInt(bitPattern: pointer)
pointer.initialize(to: existential)
if let pointer = UnsafePointer<P.Type>(bitPattern: bits) {
print(pointer)
print(pointer.pointee)
}
pointer.deinitialize(count: 1)
pointer.deallocate()
Don't forget to (de-init and) deallocate.
1 Like