首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当字符串为零时,String.withCString

当字符串为零时,String.withCString
EN

Stack Overflow用户
提问于 2017-05-19 09:02:54
回答 1查看 337关注 0票数 2

将要描述的问题与我之前的问题有关:string.withCString和UnsafeMutablePointer(变异: cstring)被包装成一个函数,这是我第一次处理零字符串(通过将withCString放入函数),以及Mecki问的一个问题:为什么我不能将一个允许空指针的可选Swift字符串传递给C函数呢?

假设有一个c-函数,类似于:

代码语言:javascript
复制
unsigned long randomSign(char *pin, char *tag_signature, char *tag_data, char *xyz);

我知道,如果围绕相应的string.withCString函数包装4个闭包,该函数就能正常工作:

代码语言:javascript
复制
// 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))
    }}}}

马丁R回答了一个更简单的例子,它不需要围绕randomSign(参数)和UnsafeMutablePointer(变异:.)包装闭包。因为它也可以接受字符串并对其进行转换。但是,当我放弃闭包并使用它作为马丁·R时,它在启动mac后第一次在模拟器上启动时就工作了,但是在随机信号函数的连续调用中,返回会告诉我,例如,tag_signature或引脚将是无效的(但它实际上是有效的,我不知道为什么?!)

这就引出了我需要withCString闭包的问题(目前),但我必须处理零字符串,这将导致应用程序在返回结果时崩溃,因为它无法评估随机函数。

所以我试着把以下方法( @Martin R也建议)装到Swift 3上,但是我没有锻炼来适应它。

代码语言:javascript
复制
//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时才能工作,而当我不接受它时,我会非常感激,如果有人知道如何解决这个问题,也就是正确地将SWIFE-2代码转换成工作的also 3代码的话。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-05-19 09:43:55

问题在于

代码语言:javascript
复制
let result = randomSign(UnsafeMutablePointer(mutating: pin),
                    UnsafeMutablePointer(mutating: tag_signature),
                    UnsafeMutablePointer(mutating: tag_data),
                    UnsafeMutablePointer(mutating: xyz))

由Swift字符串创建的临时UTF-8表示仅在UnsafeMutablePointer()的每次调用中有效,但在调用randomSign()时不一定仍然有效。(所以我在https://stackoverflow.com/a/44027397/1187415中的最后一个建议实际上是不正确的,我已经更新了这个部分)。

https://stackoverflow.com/a/39363769/1187415中包装器的一个可能的Swift 3版本是

代码语言:javascript
复制
extension Optional where Wrapped == String {
    func withOptionalCString<Result>(_ f: (UnsafeMutablePointer<Int8>?) -> Result) -> Result {
        if let string = self {
            return string.withCString { f(UnsafeMutablePointer(mutating: $0)) }
        } else {
            return f(nil)
        }
    }
}

这既处理了可选性,又将C字符串指针转换为可变指针(按照randomSign()的要求)。这可以称为

代码语言:javascript
复制
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 *参数,则可以避免此问题:

代码语言:javascript
复制
unsigned long randomSign(const char *pin, const char *tag_signature, const char *tag_data, const char *xyz);

哪一个人可以简单地称为

代码语言:javascript
复制
let result = randomSign(pin, tag_signature, tag_data, xyz)

带有可选或非可选的Swift字符串。但是,正如SR-2814 Swift不能正确地将多个可选字符串传递给C函数中所报告的,这种方法目前不起作用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44065751

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档