Инициализировать структуру C с массивом символов из swift - PullRequest
0 голосов
/ 10 марта 2019

Я пишу быстрый клиент для старого сетевого протокола на основе Си.Мне нужно отправить данные структуры через сокет TCP в определенном формате.Для этого требуется импортировать структуру C в Swift, а затем инициализировать ее (попытка создать структуру в Swift не приводит к правильному расположению памяти, когда используются массивы).

Вот пример структуры C, в которой я сделалэто успешно:

#define NAME_LEN 16

struct login_cpacket { /* CP_LOGIN py-struct '!bbxx16s16s16s' #8 */
    char type;
    char query;
    char pad2;
    char pad3;
    unsigned char name[NAME_LEN];
    unsigned char password[NAME_LEN];
    unsigned char login[NAME_LEN];
};

К сожалению, этот массив unsigned char импортируется как кортеж, которым трудно манипулировать без использования небезопасных указателей.Вот моя успешная, но грубая реализация, использующая 16-кортеж:

static func make16Tuple(string: String) -> (UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8) {
    var temp: [UInt8] = []
    for _ in 0..<16 {
        temp.append(0)
    }
    for (index,char) in string.utf8.enumerated() {
        if index < 15 {
            // leaving last position with null
            temp[index] = char
        }
    }
    let information = (temp[0],temp[1],temp[2],temp[3],temp[4],temp[5],temp[6],temp[7],temp[8],temp[9],temp[10],temp[11],temp[12],temp[13],temp[14],temp[15])
    return information
}

// CP_LOGIN 8
static func cpLogin(name: String, password: String, login: String) -> Data {
    // ugly hack with 16-element tuple and
    // C structure header to get bit boundaries to align

    var packet = login_cpacket()
    packet.type = 8
    packet.query = 0
    packet.name = make16Tuple(string: name)
    packet.login = make16Tuple(string: login)
    packet.password = make16Tuple(string: password)
    debugPrint("Sending CP_LOGIN 8 query \(packet.query) name \(name)")
    let data = Data(bytes: &packet, count: packet.size)
    return data
}

Теперь для плохих новостей: следующая структура, которую мне нужно реализовать, имеет массив из 80 символов.Я могу сделать это грубой силой с 80 кортежами, но я открыт для предложений.Я лично предпочитаю избегать небезопасных указателей.Я хотел бы получить доступ к кортежу в виде массива.

Вот новая структура:

#define MSG_LEN 80

struct mesg_cpacket { /* CP_MESSAGE py-struct "!bBBx80s" #1 */
    char type;
    char group;
    char indiv;
    char pad1;
    char mesg[MSG_LEN];
};
...