Swift - C API bridge - how to handle null pointers

大城市里の小女人 提交于 2020-01-04 01:59:29

问题


In Swift I am using C API that returns struct with char array (containing UTF8 null terminated string or null).

struct TextStruct {
   char * text;
   //other data
}

I use:

let text: String = String(cString: data.text)

This works, however, when data.text is nullptr, this fails with

fatal error: unexpectedly found nil while unwrapping an Optional value

Is there any workaround, or I have to check data.text manually before using cString ctor?


回答1:


In addition to Gwendal Roué's solution: You can annotate the C API to indicate whether the pointer can be null or not. For example,

struct TextStruct {
    char * _Nullable text;
    //other data
};

is imported to Swift as

public struct TextStruct {
    public var text: UnsafeMutablePointer<Int8>?
    // ...
}

where var text is a "strong" optional instead of an implicitly unwrapped optional. Then

let text = String(cString: data.text)
// value of optional type 'UnsafeMutablePointer<Int8>?' not unwrapped; ...

no longer compiles, and forces you to use optional binding or other unwrapping techniques, and the "fatal error: unexpectedly found nil" cannot happen anymore accidentally.

For more information, see "Nullability and Objective-C" from the Swift Blog – despite the title, it can be used with pure C as well.




回答2:


Yes, you have to check data.text, in order to make sure it can feed the String(cString:) initializer, which is documented to require a non-null pointer.

A technique is to use a if let statement. This is a classic technique for safely unwrapping optional values:

let str: String?
if let ptr = ptr {
    str = String(cString: ptr)
} else {
    str = nil
}
print("got \(str ?? "nil")")

Another technique is the Optional.map function:

let str = ptr.map { String(cString: $0) }
print("got \(str ?? "nil")")


来源:https://stackoverflow.com/questions/47375208/swift-c-api-bridge-how-to-handle-null-pointers

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!