将 Objective-C malloc 转换为 Swift

Posted

技术标签:

【中文标题】将 Objective-C malloc 转换为 Swift【英文标题】:Converting Objective-C malloc to Swift 【发布时间】:2018-11-09 20:10:13 【问题描述】:

我正在开发一个用 Objective-C 编写的项目,需要更新到 Swift。我们使用 C 文件来传输数据。

这是我在 Objective-C 中给出的代码:

- (NSData *)prepareEndPacket 
    UInt8 *buff_data;
    buff_data = (uint8_t *)malloc(sizeof(uint8_t)*(PACKET_SIZE+5));
    // Call to C File
    PrepareEndPacket(buff_data);
    NSData *data_first = [NSData dataWithBytes:buff_data length:sizeof(uint8_t)*(PACKET_SIZE+5)];
    return data_first;

在 C .h 文件中,我有这个供参考:

#define PACKET_SIZE     ((uint32_t)128)

我似乎找不到将其转换为 Swift 的好方法。任何帮助,将不胜感激。

【问题讨论】:

该代码将泄漏 malloc 的数据。它应该使用dataWithBytesNoCopy 来创建NSData 对象而不是dataWithBytes,以便NSData 对象拥有malloc'ed 数据缓冲区的所有权。 【参考方案1】:

mallocfree 实际上在 Swift 中运行良好;但是,UnsafeMutablePointer API 更“原生”。我可能会使用DatabytesNoCopy 以获得更好的性能。如果你愿意,你可以使用Data(bytes:count:),但这会复制数据(然后你需要确保在复制后释放指针,否则你会泄漏内存,这实际上是一个问题上面的 Objective-C 代码,因为它无法free 缓冲区)。

所以,类似:

func prepareEndPacket() -> Data 
    let count = PACKET_SIZE + 5
    let buf = UnsafeMutablePointer<UInt8>.allocate(capacity: count)

    PrepareEndPacket(buf)

    return Data(bytesNoCopy: buf, count: count, deallocator: .custom  ptr, _ in
        ptr.deallocate()
    )

通过使用bytesNoCopy,返回的Data 对象基本上是原始指针的包装,当Data 对象被销毁时,释放器将释放原始指针。

或者,您可以从头开始创建Data 对象并获取指向其内容的指针以传递给PrepareEndPacket()

func prepareEndPacket() -> Data 
    var data = Data(count: PACKET_SIZE + 5)

    data.withUnsafeMutableBytes  (ptr: UnsafeMutablePointer<UInt8>) in
        PrepareEndPacket(ptr)
    

    return data

稍微效率较低,因为Data(count:) 初始化程序会将所有Data 的字节初始化为零(类似于使用calloc 而不是malloc),但在在很多情况下,这可能并不足以产生影响。

【讨论】:

优秀答案(已投票)。您可能想详细了解 Objective-C 代码泄漏的原因。 @Charles Srstka 我还有一个部分可能需要帮助。它使用 memcpy @temp_ 发表一个新问题,我会看看。

以上是关于将 Objective-C malloc 转换为 Swift的主要内容,如果未能解决你的问题,请参考以下文章

将图像转换为无符号字符*

将 Java 转换为 Objective-C:异常处理

Objective-C:如何将 NSIndexSet 转换为 NSIndexPath

如何将 Objective-C 的完成块转换为 Swift?

将 Objective-C 中的函数转换为 swift

将 Objective-C 方法转换为 Swift [关闭]