【问题标题】:Swift reading char (not char *) as C string pointer快速读取 char(不是 char *)作为 C 字符串指针
【发布时间】:2018-03-16 13:10:24
【问题描述】:

这周我刚开始使用 Swift,特别是 Swift 4,我正在通过一个桥接头使用 C 库,liblo,它处理通过网络套接字发送/接收 OSC(开放声音控制)格式的消息.

我能够启动一个服务器线程,通过 C 回调->Swift 闭包接收 OSC 消息,并使用 Swift 读取数值参数值。但是,我在读取字符串值时遇到了麻烦。

liblo 消息参数类型lo_arg is a C typedef for a union 和字符串参数类型被声明为简单的字符,它们作为 Int8 映射到 Swift。

在 C 中,您可以通过 &argv[i]->s 从回调的 lo_arg **argv 数组中获取字符串。在一个带有 liblo 的 Obj-C 项目中,我使用:

// 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() ala print("strlen: \(strlen($0)") 只会打印“1”的长度。我已经验证了一个多字符串确实是通过非 Swift 测试程序发送的。我现在想知道 Swift 是否以某种方式假设字符串是单个字符而不是 C 字符串头地址和/或我需要进一步的指针转换。

【问题讨论】:

    标签: swift osc


    【解决方案1】:

    经过一番挖掘,我可以确认 Swift 在我的 64 位系统(即 sizeof(char))上将 lo_arg->slo_arg->S 字符串值截断为 8 个字节。当试图从 来自 Swift 的 lo_arg 中读取字符串时会发生这种情况。 在 C 中读取相同的值可以正常工作,因此 Swift 似乎只保留/允许从单个字符的空间中读取。将 lo_arg 从 Swift 转发到 C 并通过 printf() 打印字符串也会显示最多 8 个字符的截断字符串。

    快速解决方法是避免从 Swift 生成的 lo_arg 中读取字符串,从 C 中的原始 lo_message 中获取 lo_arg,并将 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 中,我可以转换为字符串:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-23
      • 1970-01-01
      • 2018-09-25
      • 2015-05-19
      • 2010-12-12
      • 1970-01-01
      • 2021-03-30
      • 1970-01-01
      相关资源
      最近更新 更多