我遇到了String.withCString {}和UnsafeMutablePointer(mutating:...)的问题。
鉴于:像这样的C函数
randomSign(xml_string: UnsafeMutablePointer<Int8>!) -> Uint
还给出了:像
这样的字符串str = "some xml_tag"
我的工作代码是这样的(VERSION_1)
func randomSignWrapper_1(xml_tag_str: String) -> Uint {
let result = xml_str.withCString { s in return
randomSign(UnsafeMutablePointer(mutating: s))
}
return result
}
但我希望将withCString放入一个单独的函数中:
func testFunction(_ x: String) -> UnsafeMutablePointer<Int8>{
return x.withCString{s in
return UnsafeMutablePointer(mutating: s)
}
}
这样我就可以轻松地重复使用它(VERSION_2)
func randomSignWrapper_2(xml_tag_str: String) -> Uint {
let result = randomSign(testFunction(xml_tag_str))
return result
}
但问题是VERSION_1提供了正确的返回值,而VERSION_2在某种程度上无法正常工作,并告诉我数据是错误的。 我想知道它为什么会这样? 如何解决这个问题,我可以用它描述的方式使用它?
答案 0 :(得分:0)
withCString { ... }
创建Swift的临时表示
string作为以null结尾的UTF-8序列,仅在内部有效
关闭。将指针传递给闭包的外部是
未定义的行为。
另请注意,您无法使用该指针改变字符串。
传递UnsafeMutablePointer(mutating: $0)
仅使编译器成为可能
相信指向内存是可变的,但实际上是在做
所以未定义的行为也可能会崩溃。
如果randomSign()
函数没有修改给定的
字符串然后最好的解决方案是将其C声明更改为
取一个常量字符串:
unsigned long randomSign(const char *xml_string);
这将作为
导入Swiftfunc randomSign(_ xml_string: UnsafePointer<Int8>!) -> UInt
现在您可以将Swift字符串直接传递给该函数:
let str = "some xml_tag"
let result = randomSign(str)
编译器会自动插入用于创建的代码 临时UTF-8表示并将其传递给函数,比较String value to UnsafePointer<UInt8> function parameter behavior。
如果您无法更改C声明,那么您仍然可以调用它
如击>
let str = "some xml_tag"
let result = randomSign(UnsafeMutablePointer(mutating: str))
也不需要你自己的帮助函数。
更新:最后一条建议不正确。由...创建的临时字符串
编译器仅在UnsafeMutablePointer()
的调用期间
但在调用randomSign()
期间不一定有效。
答案 1 :(得分:0)
检查reference of withCString(_:)
。
讨论
withCString(_ :)方法确保序列的生命周期 通过执行身体延伸。 body的指针参数是 仅在关闭的生命周期内有效。不要逃避它 关闭供以后使用。
您的VERSION_2代码正在尝试将其从闭包中转义以供以后使用。它不是withCString(_:)
的有效用法。
包含String
的UTF-8表示的区域是临时的,Swift运行时将随时释放它。
你可以这样写:
func utf8Array(from string: String) -> [Int8] {
return string.cString(using: .utf8)!
}
func randomSignWrapper_3(xml_tag_str: String) -> UInt {
var charArray = utf8Array(from: xml_tag_str)
let result = randomSign(xml_string: &charArray)
return result
}
但我想知道你是否需要定义像utf8Array(from:)
这样的函数。