Преобразование Objective-C malloc в Swift - PullRequest
0 голосов
/ 09 ноября 2018

Я работаю над проектом, который был написан на 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. Любая помощь будет оценена.

1 Ответ

0 голосов
/ 09 ноября 2018

malloc и free на самом деле отлично работают в Swift; однако API UnsafeMutablePointer более "родной". Я бы, вероятно, использовал Data bytesNoCopy для лучшей производительности. Если вы хотите, вы можете использовать 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), но во многих случаи, которые могут не иметь достаточного значения, чтобы иметь значение.

...