Току-що започнах със Swift тази седмица, по-специално Swift 4, и използвам C библиотека чрез мостово заглавие, liblo, който обработва изпращане / получаване на форматирани съобщения от OSC (Open Sound Control) през мрежов сокет.
Мога да стартирам сървърна нишка, да получа OSCсъобщения чрез C callback-> Swift затваряне и прочетете числовите стойности на аргумента с Swift просто добре. Имам проблеми обаче с четене на низови стойности.
Типът аргумент на съобщението liblo lo_arg е тип type C за съюз и типовете аргументи на низ са декларирани като прости знаци, които са картографирани на Swift като Int8.
В C можете да вземете низа чрез &argv[i]->s
от обратното ви обаждане "s lo_arg **argv
масив. В проект Obj-C с liblo, използвам:
// get string value of first argument
lo_arg arg = argv[0];
NSString *s = [NSString stringWithUTF8String:&arg->s];
// do something with s
В Swift опитах да получа адреса на Int8 и да го предам на String, който работи, но само хваща първия символ:
// get string value of first argument
if var arg : lo_arg = argv?.pointee![0] {
withUnsafePointer(to: &arg.s) {
let s = String(cString: $0)
// so something with s
}
}
Правя ли нещо нередно? Мисля, че те биха били равностойни, но преминаващи $0
да се strlen()
ала print("strlen: (strlen($0)")
отпечатва само дължина "1". Проверих, че многосимволен низ наистина се изпраща с тестова програма, която не е Swift. Питам се сега дали Swift по някакъв начин приема, че низът е един символ, вместо главен адрес на C низ и / или имам нужда от още преобразуване на показалец
Отговори:
0 за отговор № 1След като копая, мога да потвърдя, че Суифт прерязва lo_arg->s
& lo_arg->S
низови стойности до 8 байта в 64-битовата ми система aka sizeof(char)
, Това се случва при опит да се прочете низът от идващия lo_arg от Суифт, Четене на една и съща стойност в С работи отлично, така че изглежда Суифт резервира / позволява да се чете само от пространството за една карта. Препращане на lo_arg от Swift до C и отпечатване на низа чрез printf()
показва също пресечени низове до 8 знака.
Бързото поправяне е да се избегне четенето на низоветеот lo_arg, генериран от Swift, вземете lo_arg от суровия lo_message в C и хвърлете char "показалеца" към const char * Swift ще разбере като низ с променлива дължина. Ето някои функции на полезните полезни програми, които добавих към мостовия си заглав:
/// return an lo_message argv[i]->s in a format Swift can understand as a String
const char* lo_message_get_string(lo_message message, int at) {
return (const char *)&lo_message_get_argv(message)[at]->s;
}
/// return an lo_message argv[i]->S in a format Swift can understand as a String
const char* lo_message_get_symbol(lo_message message, int at) {
return (const char *)&lo_message_get_argv(message)[at]->S;
}
След това в Swift мога да конвертирам в String:
let s = String(cString: lo_message_get_string(msg, 0))
// do something with s