Swift将Data转换为UnsafeMutablePointer <Int8>

7
我正在从Swift中调用Objective-C类中的一个函数。
-(char *)decrypt:(char *)crypt el:(int)el{}

当从Swift调用此函数时,它要求将UnsafeMutablePointer<Int8>作为参数'crypt'的值。

'crypt'的值来自服务器,是一个base64编码的字符串。因此,我对该字符串进行解码并获得了一个Data对象。

let resultData = Data(base64Encoded: base64String)

现在我需要将这个数据传递给上面提到的函数。我尝试将这个Data对象转换为UnsafeMutablePointer<Int8>

resultData?.withUnsafeBytes { (u8Ptr: UnsafeMutablePointer<Int8>) in
                    let decBytes = tea?.decrypt(u8Ptr , el: el)}

但它无法编译。出现以下错误:

'UnsafeMutablePointer' 无法转换为 'UnsafePointer<_>'

我对 Objective-C 不是很了解,所以有人能帮我将此参数传递给 Objective-C 函数吗?


请查看此答案 https://dev59.com/gFkS5IYBdhLWcg3wgXHf - Abdelahad Darwish
@AbdelahadDarwish 我已经检查了答案。它建议使用以下代码:var ptr = data.bytes.assumingMemoryBound(to: UInt8.self)。但是在 Swift 4 中,data.bytes 不可用。 - udi
3个回答

8

您需要将UnsafeMutablePointer更改为UnsafePointer

UnsafePointer

resultData?.withUnsafeBytes {(bytes: UnsafePointer<CChar>)->Void in
            //Use `bytes` inside this closure

        }
不安全可变指针
 var data2 = Data(capacity: 1024)
data2.withUnsafeMutableBytes({ (bytes: UnsafeMutablePointer<UInt8>) -> Void in
                 //Use `bytes` inside this closure

            })

1
我使用了您的第二段代码,并将UnsafeMutablePointer<UInt8>)更改为UnsafeMutablePointer<Int8>)。现在它可以工作了。非常感谢您的帮助。 - udi
1
我收到错误信息:'UnsafeMutablePointer<UInt8>' 无法转换为 'UnsafeMutablePointer<_>'。 - iosbegindevel

3

编辑,更新我的答案,有两点需要注意:

  • 不要从 withUnsafeBytes 中返回指针
  • 考虑到 Swift 5 的弃用警告:'withUnsafeBytes' is deprecated: use withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R instead
// buffer pointer captured is converted to byte pointer which is used in the block to decode the base64 encoded Data
encodedStringData.withUnsafeMutableBytes { (rawBufferPtr: UnsafeMutableRawBufferPointer) in
    if let rawPtr = rawBufferPtr.baseAddress {
        let decodedString = String(bytesNoCopy: rawPtr, length: rawBufferPtr.count, encoding: .utf8, freeWhenDone: false)
        print(decodedString!)
    }
}

someData.withUnsafeBytes { (bufferRawPtr: UnsafeRawBufferPointer) in
        // For converting an UnsafeRawBufferPointer to its typed variant, in this case UnsafeBufferPointer<UInt8>
            let bufferTypedPtr = bufferRawPtr.bindMemory(to: UInt8.self)

        // Then, getting the typed UnsafePointer, in this case UnsafePointer<UInt8>
            let unsafePointer = bufferTypedPtr.baseAddress!
        }

注意:Swift 5 不允许您从 withUnsafeMutableBytes 块内访问 encodedStringData!阅读 Swift 5 Exclusivity Enforcement 了解why
捕获块外的指针似乎不被推荐,它可以工作,但行为在未来可能变得不确定。
旧答案:
这将帮助那些想要获取 Data 对象的底层原始字节(以 UnsafeMutablePointer<UInt8> 表示)作为变量以供进一步使用的人(而不是必须在 withUnsafeMutableBytes 块中编写所有逻辑)。
var encodedStringData = Data(base64Encoded: "Vmlub2QgaXMgZ3JlYXQh")!
    
// byte pointer variable used later to decode the base64 encoded Data
let rawPtr: UnsafeMutablePointer<UInt8> = encodedStringData.withUnsafeMutableBytes { (bytePtr: UnsafeMutablePointer<UInt8>) in bytePtr }

let decodedString = String(bytesNoCopy: rawPtr, length: encodedStringData.count, encoding: .utf8, freeWhenDone: false)

print(decodedString, encodedStringData)

1
不要让你的不安全指针逃离它们原本预定的 withUnsafe*Bytes 作用域。 - lhunath

2

使用NSData的解决方案

let data = NSData(bytes: arrayOfUInt8, length: arrayOfUInt8.count)
let pointer: UnsafeMutablePointer<Int8> = data.bytes.assumingMemoryBound(to: UInt8.self)

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