/ / Charla de lectura rápida (no char *) como puntero de cadena C - swift, osc

Lectura rápida char (no char *) como puntero de cadena C - swift, osc

Acabo de comenzar con Swift esta semana, específicamente Swift 4, y estoy usando una biblioteca C a través de un encabezado de puente, liblo, que maneja el envío / recepción de mensajes con formato OSC (Open Sound Control) a través de un socket de red.

Puedo iniciar un hilo del servidor, recibir OSCmensajes a través de la devolución de llamada C-> cierre de Swift, y lea los valores de argumento numérico con Swift muy bien. Sin embargo, estoy teniendo problemas con la lectura de valores de cadena.

El tipo de argumento del mensaje liblo lo_arg es una definición de tipo C para una unión y los tipos de argumentos de cadena se declaran como caracteres simples que se asignan a Swift como Int8.

En C, puede agarrar la cadena a través de &argv[i]->s de su devolución de llamada "s lo_arg **argv formación. En un proyecto Obj-C con liblo, uso:

// get string value of first argument
lo_arg arg = argv[0];
NSString *s = [NSString stringWithUTF8String:&arg->s];
// do something with s

En Swift, he intentado obtener la dirección de Int8 y alimentarla a String, que funciona, pero solo toma el primer carácter:

// 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
}
}

¿Estoy haciendo algo mal? Creo que estos serían equivalentes, pero pasando $0 a strlen() ala print("strlen: (strlen($0)") solo imprime una longitud de "1". Verifiqué que se está enviando una cadena de caracteres múltiples con un programa de prueba que no es Swift. Ahora me pregunto si Swift está asumiendo de alguna manera que la cadena es un solo carácter en lugar de la dirección del encabezado de la cadena C y / o necesito más Conversión de puntero.

Respuestas

0 para la respuesta № 1

Después de investigar un poco, puedo confirmar que Swift trunca el lo_arg->s & lo_arg->S valores de cadena a 8 bytes en mi sistema de 64 bits, también conocido como sizeof(char). Esto sucede cuando intenta leer la cadena de un lo_arg que viene de Swift. Leyendo el mismo valor Cía funciona bien, por lo que Swift parece reservar / permitir la lectura solo desde el espacio para un solo personaje. Reenviar lo_arg de Swift a C e imprimir la cadena a través de printf() también muestra cadenas truncadas de hasta 8 caracteres.

La solución rápida es evitar leer las cadenas.desde el lo_arg generado por Swift, tome un lo_arg del lo_message sin procesar en C, y convierta el "puntero" char en un constante char * Swift lo entenderá como una cadena de longitud variable. Aquí hay algunas funciones de utilidad de trabajo que agregué a mi encabezado de puente:

/// 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;
}

En Swift, puedo convertir a una cadena:

let s = String(cString: lo_message_get_string(msg, 0))
// do something with s