elect86
(Giuseppe Barbieri)
1
I have a big C struct expecting a UnsafePointer<VkPhysicalDeviceFeatures>?
Since withUnsafePointer work only with non Optional, I'm trying to determine if the field containing VkPhysicalDeviceFeatures is nil or not, and if not, assign its reference to a variable
var enabledFeatures: VkPhysicalDeviceFeatures?
func native<R>(_ block: (VkDeviceCreateInfo) -> R) -> R {
var pFeatures: UnsafePointer<VkPhysicalDeviceFeatures>?
if var features = enabledFeatures {
pFeatures = &features
}
return block(VkDeviceCreateInfo(
...
pEnabledFeatures: &features))
}
}
but the compiler keeps complaining:
error: use of extraneous '&'
then I'm forced to do the following:
var enabledFeatures: VkPhysicalDeviceFeatures?
func native<R>(_ block: (VkDeviceCreateInfo) -> R) -> R {
if var features = enabledFeatures {
return block(VkDeviceCreateInfo(
...
pEnabledFeatures: &features))
}
return block(VkDeviceCreateInfo(
...
pEnabledFeatures: nil))
}
which is obviously quite verbose and annoying..
Do I have a better choice?
Nevin
2
If I understand correctly, you have a variable of type T?, and a function which takes an argument of type UnsafePointer<T>?, and you want to lift the variable so you can pass it to the function. Is that correct?
Nevin
4
Try this:
if var features = enabledFeatures {
pFeatures = UnsafePointer(&features)
}
2 Likes
Martin
(Martin R)
5
Unless I am mistaken, that would be undefined behavior: A pointer to the variable storage is created and passed to the UnsafePointer constructor. That pointer must not be used after the function (here: the init method) returns.
4 Likes
elect86
(Giuseppe Barbieri)
6
I just need it in block, there should be still valid, shouldn't?
Martin
(Martin R)
7
I don't think so. But what you could do is to define a helper function, similar to the existing withUnsafePointer function:
public func withOptionalUnsafePointer<T, Result>(to value: T?, _ body: (UnsafePointer<T>?) -> Result) -> Result {
if let value = value {
return withUnsafePointer(to: value, body)
} else {
return body(nil)
}
}
and use it like
return withOptionalUnsafePointer(to: enabledFeatures) {
block(VkDeviceCreateInfo(pEnabledFeatures: $0))
}
But again note that the pointer in $0 is only valid for the execution of the block. (If I remember correctly, only global variables and static member variables are guaranteed to have a fixed address.)
lukasa
(Cory Benfield)
8
@Martin is 100% correct. Creating an UnsafePointer using the UnsafePointer(&foo) when foo is a Swift type is never valid, it creates a pointer that is immediately invalid and must not be used. The correct thing to do is to use the withUnsafePointer function along with a helper that can handle optionality.
Might be a good candidate for a warning.
lukasa
(Cory Benfield)
10
2 Likes