String.withCString 当字符串为 nil 时
String.withCString when the String is nil
将要描述的问题与我之前的问题有关:
string.withCString and UnsafeMutablePointer(mutating: cstring) wrapped into a function 这是我处理 nil 字符串的第一种方法(通过将 withCString 放入函数中)
以及 Mecki 提出的一个问题:
Why can't I pass an optional Swift String to C function that allows NULL pointers?
假设有一个 c 函数如下:
unsigned long randomSign(char *pin, char *tag_signature, char *tag_data, char *xyz);
我知道如果我在相应的 swift 函数周围包装 4 个 string.withCString 闭包,该函数可以正常工作:
// pin, tag_signature, tag_data and xyz are optional Strings so they may be nil which is a problem for my result.
// corresponding swift function:
// randomSign(pin: UnsafeMutablePointer<Int8>!, tag_signature: UnsafeMutablePointer<Int8>!, tag_data: UnsafeMutablePointer<Int8>!, xyz: UnsafeMutablePointer<Int8>!)
let result = pin.withCString { s1 in return
tag_signature.withCString {s2 in return
tag_data.withCString {s3 in return
xyz.withCString { s4 in return
randomSign(UnsafeMutablePointer(mutating: s1), UnsafeMutablePointer(mutating: s2), UnsafeMutablePointer(mutating: s3), UnsafeMutablePointer(mutating: s4))
}}}}
And so Martin R replied to an easier example,不需要将闭包包裹在 randomSign(arguments) 和 UnsafeMutablePointer(mutating: ...) 周围,因为它也可以获取字符串并进行转换。
但是当我放弃闭包并将其用作 Martin R described 时,它在启动 mac 后直接在模拟器上首次启动时工作,但在连续调用 randomSign-Function 时 return会告诉我,例如 tag_signature 或 pin 无效(但它实际上是有效的,我不知道为什么?!)。
这让我遇到了一个问题,我需要 withCString 闭包(目前),但我必须处理 nil-Strings,这会导致应用程序在它应该 return 结果时崩溃,因为它无法计算 randomSign-Function。
所以我试着把the approach below (also suggested by @Martin R)装到Swift3,但是我没有锻炼适应它。
//Swift-2 written by Martin R
protocol CStringConvertible {
func withCString<Result>(@noescape f: UnsafePointer<Int8> throws -> Result) rethrows -> Result
}
extension String: CStringConvertible { }
extension Optional where Wrapped: CStringConvertible {
func withOptionalCString<Result>(@noescape f: UnsafePointer<Int8> -> Result) -> Result {
if let string = self {
return string.withCString(f)
} else {
return f(nil)
}
}
}
//Swift 3: ???
如果有人能告诉我,为什么我的函数只在我使用 withCString 时有效,而在我关闭它时却无效,我将不胜感激
并且如果有人知道如何解决该问题,即正确地将 swift-2 代码转换为工作 swift-3 代码。
的问题
let result = randomSign(UnsafeMutablePointer(mutating: pin),
UnsafeMutablePointer(mutating: tag_signature),
UnsafeMutablePointer(mutating: tag_data),
UnsafeMutablePointer(mutating: xyz))
是从 Swift 创建的临时 UTF-8 表示
字符串仅在 UnsafeMutablePointer()
的每次调用期间有效,
但在 randomSign()
的调用期间不一定仍然有效。
(所以我在 中的最终建议
实际上是不正确的,我已经更新了那部分。
中可能的 Swift 3 包装器版本是
extension Optional where Wrapped == String {
func withOptionalCString<Result>(_ f: (UnsafeMutablePointer<Int8>?) -> Result) -> Result {
if let string = self {
return string.withCString { f(UnsafeMutablePointer(mutating: [=11=])) }
} else {
return f(nil)
}
}
}
这处理了可选性 和 强制转换 C 字符串指针
到可变指针(根据 randomSign()
的要求)。这可以是
称为
let result = pin.withOptionalCString { s1 in
tag_signature.withOptionalCString { s2 in
tag_data.withOptionalCString { s3 in
xyz.withOptionalCString { s4 in
randomSign(s1, s2, s3, s4)
}
}
}
}
备注:理论上把randomSign()
的签名改成带const char *
个参数就可以避免这个问题:
unsigned long randomSign(const char *pin, const char *tag_signature, const char *tag_data, const char *xyz);
哪个可以简单地称为
let result = randomSign(pin, tag_signature, tag_data, xyz)
带有可选或非可选的 Swift 字符串。
但是,这目前不起作用,如中所述
SR-2814 Swift does not correctly pass in multiple optional strings to C function.
将要描述的问题与我之前的问题有关: string.withCString and UnsafeMutablePointer(mutating: cstring) wrapped into a function 这是我处理 nil 字符串的第一种方法(通过将 withCString 放入函数中) 以及 Mecki 提出的一个问题: Why can't I pass an optional Swift String to C function that allows NULL pointers?
假设有一个 c 函数如下:
unsigned long randomSign(char *pin, char *tag_signature, char *tag_data, char *xyz);
我知道如果我在相应的 swift 函数周围包装 4 个 string.withCString 闭包,该函数可以正常工作:
// pin, tag_signature, tag_data and xyz are optional Strings so they may be nil which is a problem for my result.
// corresponding swift function:
// randomSign(pin: UnsafeMutablePointer<Int8>!, tag_signature: UnsafeMutablePointer<Int8>!, tag_data: UnsafeMutablePointer<Int8>!, xyz: UnsafeMutablePointer<Int8>!)
let result = pin.withCString { s1 in return
tag_signature.withCString {s2 in return
tag_data.withCString {s3 in return
xyz.withCString { s4 in return
randomSign(UnsafeMutablePointer(mutating: s1), UnsafeMutablePointer(mutating: s2), UnsafeMutablePointer(mutating: s3), UnsafeMutablePointer(mutating: s4))
}}}}
And so Martin R replied to an easier example,不需要将闭包包裹在 randomSign(arguments) 和 UnsafeMutablePointer(mutating: ...) 周围,因为它也可以获取字符串并进行转换。 但是当我放弃闭包并将其用作 Martin R described 时,它在启动 mac 后直接在模拟器上首次启动时工作,但在连续调用 randomSign-Function 时 return会告诉我,例如 tag_signature 或 pin 无效(但它实际上是有效的,我不知道为什么?!)。
这让我遇到了一个问题,我需要 withCString 闭包(目前),但我必须处理 nil-Strings,这会导致应用程序在它应该 return 结果时崩溃,因为它无法计算 randomSign-Function。
所以我试着把the approach below (also suggested by @Martin R)装到Swift3,但是我没有锻炼适应它。
//Swift-2 written by Martin R
protocol CStringConvertible {
func withCString<Result>(@noescape f: UnsafePointer<Int8> throws -> Result) rethrows -> Result
}
extension String: CStringConvertible { }
extension Optional where Wrapped: CStringConvertible {
func withOptionalCString<Result>(@noescape f: UnsafePointer<Int8> -> Result) -> Result {
if let string = self {
return string.withCString(f)
} else {
return f(nil)
}
}
}
//Swift 3: ???
如果有人能告诉我,为什么我的函数只在我使用 withCString 时有效,而在我关闭它时却无效,我将不胜感激 并且如果有人知道如何解决该问题,即正确地将 swift-2 代码转换为工作 swift-3 代码。
let result = randomSign(UnsafeMutablePointer(mutating: pin),
UnsafeMutablePointer(mutating: tag_signature),
UnsafeMutablePointer(mutating: tag_data),
UnsafeMutablePointer(mutating: xyz))
是从 Swift 创建的临时 UTF-8 表示
字符串仅在 UnsafeMutablePointer()
的每次调用期间有效,
但在 randomSign()
的调用期间不一定仍然有效。
(所以我在 中的最终建议
实际上是不正确的,我已经更新了那部分。
中可能的 Swift 3 包装器版本是
extension Optional where Wrapped == String {
func withOptionalCString<Result>(_ f: (UnsafeMutablePointer<Int8>?) -> Result) -> Result {
if let string = self {
return string.withCString { f(UnsafeMutablePointer(mutating: [=11=])) }
} else {
return f(nil)
}
}
}
这处理了可选性 和 强制转换 C 字符串指针
到可变指针(根据 randomSign()
的要求)。这可以是
称为
let result = pin.withOptionalCString { s1 in
tag_signature.withOptionalCString { s2 in
tag_data.withOptionalCString { s3 in
xyz.withOptionalCString { s4 in
randomSign(s1, s2, s3, s4)
}
}
}
}
备注:理论上把randomSign()
的签名改成带const char *
个参数就可以避免这个问题:
unsigned long randomSign(const char *pin, const char *tag_signature, const char *tag_data, const char *xyz);
哪个可以简单地称为
let result = randomSign(pin, tag_signature, tag_data, xyz)
带有可选或非可选的 Swift 字符串。 但是,这目前不起作用,如中所述 SR-2814 Swift does not correctly pass in multiple optional strings to C function.