Since you call UnsafeMutableBufferPointer<Int8>.allocate, you're allocating memory on the heap. You are also responsible for deallocating that memory via UnsafeMutableBufferPointer<Int8>.deallocate (I can't remember if we guarantee malloc/free-compatibility, but I think we do?). So like it is, you're leaking memory.
The better/correct way to do this depends on the API you are wrapping, and what kind of API you want to expose. Since Strings have lifetime considerations, I would recommend creating your own ApplicationInfo struct which stores that data in Swift-native, ARC-ed types like String, and using a scoped function to call in to C-land:
(I'm pretending these are not optional to make the example clearer)
struct ApplicationInfo {
let name: String
let engineName: String
// ...
func withVkApplicationInfo<R>(_ perform: (VkApplicationInfo) throws -> R) rethrows -> R {
name.withCString { namePtr in
engineName.withCString { engineNamePtr in
let cVal = VkApplicationInfo(..., namePtr, engineNamePtr, ...)
try perform(cVal)
}
}
}
}
let myApp = ApplicationInfo(name: "Hello, world", engineName: "MyEngine")
myApp.withVkApplicationInfo { vkApp in
// Do something with your C struct.
// String lifetime is handled automatically.
}
This gives Swift users all of our nice String APIs, and (IIRC) getting a C string does not perform any copying, because Swift Strings are already null-terminated UTF8, so it should be pretty cheap to bridge the structure over in to C when you need to.
Swift can promote heap allocations to the stack as an optimization (involving either UnsafeMutablePointer or ManagedBuffer), but there's no way today to force a stack allocation.*
* …except by writing a C function with a callback.
func withCStringOrNullPointer<R>(_ s: String?, _ perform: (UnsafePointer<Int8>?) throws -> R) rethrows -> R {
if let val = s { return try val.withCString(perform) }
return try perform(nil)
}
let name: String? = nil
withCStringOrNullPointer(name) { namePtr in
// namePtr will be nil
}
withCString accesses String's internal implementation details; I don't think it's possible to duplicate it exactly.
EDIT: Corrected types. Wrote this in the browser without checking.
I don't think so - rethrows lets the compiler know that if the given closure doesn't throw, the overall function will never throw, so it never needs to check if registers contain an error value.