Hi Jordan. Thanks for the lengthy answer.
> On Mar 1, 2017, at 6:21 PM, Jordan Rose <jordan_r...@apple.com> wrote: > > Hey, Kenny. The const vs non-const part is important, since both the implicit > conversion and cString(using:) are allowed to return a pointer to the > internal data being used by the String, and modifying that would be breaking > the rules (and could potentially cause a crash). In the case of 'fieldSep', > it's unlikely that anyone is going to mutate the contents of the string; it > was probably just the original author (you?) not bothering to be > const-correct. If you control this struct, a better fix would be to use > 'const char *' for the field. This is the PostgreSQL client library, so I don’t really want to change it. (Although the source is available. Maybe I should submit a patch…) > That said, that's not the main isuse. The implicit conversion from String to > UnsafePointer<CChar> is only valid when the string is used as a function > argument, because the conversion might need to allocate temporary storage. In > that case, it’s important to know when it’s safe to deallocate that storage. > For a function call, that’s when the call returns, but for storing into a > struct field it’s completely unbounded. So there’s no implicit conversion > there. > > If you’re willing to limit your use of the pointer value to a single block of > code, you can use withCString > <https://developer.apple.com/reference/swift/string/1538904-withcstring>: > > myString.withCString { > var opt :PQprintOpt = PQprintOpt() > opt.fieldSep = UnsafeMutablePointer(mutating: $0) > // use 'opt' > } Unfortunately, this is not always an option, since there are multiple char * files in PQprintOpt. Or could I just nest .withCString calls? Looks ugly, but might work, I guess. > Note that it is illegal to persist the pointer value beyond the execution of > withCString, because it might point to a temporary buffer. > > Alternately, if you’re willing to call free() later, you can use the C > function strdup: > > opt.fieldSep = strdup(myString) > // use ‘opt’ > free(opt.fieldSep) > > > Of course, all of this is overkill for a string literal. Perhaps when Swift > gets conditional conformances, we could consider making UnsafePointer<CChar> > conform to ExpressibleByStringLiteral. Meanwhile, you can use the type > designed specifically for this purpose, StaticString > <https://developer.apple.com/reference/swift/staticstring>: > > let separator: StaticString = “|” > opt.fieldSep = UnsafeMutablePointer(mutating: separator.utf8start) > > Note that you still have to do the init(mutating:) workaround for the fact > that you’re not allowed to mutate this string. Ah - that's >> >> Also, why is the conversion to Swift an IUO? NULL is a totally valid value >> for fieldSep. > > You're welcome to mark that field as _Nullable on the C side, but without > annotations Swift makes very few assumptions about pointers imported from C. If it’s “making very few assumptions”, I would think that, for safety’s sake, functions that return a pointer would always be optional, forcing the user to deal with any possible null pointer returns. > Hope that helps! Definitely! -Kenny
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users