在Swift中使用termios

5
现在我们已经到了Swift 2.0,我决定将尚未完成的OS X应用程序转换为Swift。虽然取得了进展,但我在使用termios时遇到了一些问题,需要一些澄清和建议。
在Swift中,termios结构被视为结构体,这并不奇怪,但令人惊讶的是,结构中的控制字符数组现在变成了元组。我本以为它只是一个数组。你可以想象我花了一段时间来弄清楚这个问题。如果我在Playground中进行操作:
var settings:termios = termios()
print(settings)

那么我将会打印出与该结构体相关的正确细节。

在Objective-C中,如果要设置控制字符,可以使用以下命令:

cfmakeraw(&settings);
settings.c_cc[VMIN] = 1;

VMIN 是在 termios.h 中等于 16 的 #define。在 Swift 中,我需要执行以下操作:

cfmakeraw(&settings)
settings.c_cc.16 = 1

这个方法可以运行,但有些晦涩难懂。我更倾向于使用类似以下的方法:

settings.c_cc.vim = 1

然而,我无法找到任何描述Swift“版本”的termios的文档。有人知道这个元组是否为其元素预分配了名称,如果没有,是否有一种方法可以在事后分配名称?我应该创建具有命名元素的自己的元组,然后将其赋值给settings.c_cc吗?

有趣的是,尽管预处理器指令不应该在Swift中工作,但如果我这样做

print(VMIN)
print(VTIME)

如果正确的值被打印出来且没有编译错误,那么这是正确的。如果有任何疑问或评论,请告知。这是一个错误吗?

剩余的问题与termios的进一步配置有关。

cfsetspeed的定义如下:

func cfsetspeed(_: UnsafeMutablePointer<termios>, _: speed_t) -> Int32

speed_t 被 typedef 为无符号长整型。在 Obj-C 中,我们会这样做:

cfsetspeed(&settings, B38400);

但是由于B38400在termios.h中被定义为# define,我们无法再这样做。苹果是否在Swift中设置了替换全局常量的内容,如果有,是否有人告诉我它们在哪里记录。另一种选择似乎是只插入原始值并失去可读性,或者创建我自己的以前在termios.h中定义的常量版本。如果没有更好的选择,我很乐意走这条路。

2个回答

3

让我们先从你的第二个问题开始,这个问题比较容易解决。B38400 在Swift中可用的,只是类型不正确。因此,你需要显式地进行转换:

var settings = termios()
cfsetspeed(&settings, speed_t(B38400))

我所知道的,你的第一个问题没有“好”的解决方案。 在Swift中,固定大小的数组被导入为元组,而且据我所知,你无法使用变量来访问元组元素。

然而,Swift 保留了从C导入的结构体的内存布局,正如苹果工程师Joe Groff所确认的那样:。因此,您可以取得元组的地址并将其“重新绑定”到指向元素类型的指针:

var settings = termios()
withUnsafeMutablePointer(to: &settings.c_cc) { (tuplePtr) -> Void in
    tuplePtr.withMemoryRebound(to: cc_t.self, capacity: MemoryLayout.size(ofValue: settings.c_cc)) {
        $0[Int(VMIN)] = 1
    }
}

(Swift 4+更新了代码。)

0
由于 c_cc 是一个字节数组,例如 [UInt8] ,您可以执行以下操作
var tty = termios()

withUnsafeMutableBytes(of: &tty.c_cc)
{
    c_cc in
    c_cc[size_t(VMIN)]  = 1
    c_cc[size_t(VTIME)] = 0
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接