从const char*转换为Swift字符串

5

我有一个C函数,我从桥接头文件中访问它,并返回一个const char*

const char* get_c_string();

然后我尝试将其转换为Swift字符串:

let str = String.fromCString(UnsafePointer<Int8>(get_c_string()))
print(str)

但它只是打印出了垃圾:
Optional("\u{14}\0\0")

我可以找到如何将Swift字符串传递给C,但不能反过来。我该如何将const char*转换为Swift字符串?
谢谢!

此字符串包含特殊字符? - Alvaro Silvino
不,这只是一个标准的 const char* C 字符串(来自于一个 std::string)。 - Pat Mustard
你的示例中有两个不同的函数get_c_stringcall_hi。除此之外,你的转换方法应该是有效的。请注意,指针转换并非必要:let str = String.fromCString(get_c_string()) - Martin R
打字错误 - 调用匹配了原型,所以我正在调用正确的函数。看起来像是编码问题,但不确定是什么。 - Pat Mustard
也许 get_c_string() 返回的是一个本地变量的内容(当函数返回时就会失效)?你必须确保返回的指针在函数返回时仍然有效(例如,分配内存或使用 strdup 复制字符串)。你的 Swift 代码是正确的。 - Martin R
没错 - 你懂了!我的 C 语言比我想象中的生疏 o_O 你想把它放在答案里让我接受吗? - Pat Mustard
1个回答

17

你的 Swift 代码是正确的,你可以稍微缩短一下:

// Swift 2:
let str = String.fromCString(get_c_string())
// Swift 3:
let str = String(cString: get_c_string())

然而,您必须确保从C函数返回的指针在函数返回时仍然有效。例如

const char* get_c_string() {
    char s[] = "abc";
    return s;
}

返回本地堆栈变量的地址,这是未定义行为。

你可能需要复制该字符串(然后考虑何时何地释放内存)。


此 API 的使用已不再当前。编译器报告:“请改用 String.init?(validatingUTF8:)。请注意,它不再接受 NULL 作为有效输入。还可以考虑使用 String(cString:),它将尝试修复格式不正确的代码单元。” - sandover
@sandover:以上代码在Xcode 7.3/Swift 2.2下仍然可以编译通过,而这也是当前的发布版本。但是在Swift 3中API似乎会发生变化,所以一旦官方发布了新版本,我将更新答案。 - Martin R
我本以为这就是我遇到的问题,但我不认为是这样。如果您在此方面有类似的见解,希望能听听您的想法:http://stackoverflow.com/questions/37776867/swift-string-from-c-string-has-correct-length-but-incorrect-contents - johnbakers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接