在 Swift 中使用 termios

问题描述 投票:0回答:2

现在我们已经达到了 Swift 2.0,我决定将我尚未完成的 OS X 应用程序转换为 Swift。取得了进展,但我在使用 termios 时遇到了一些问题,需要一些澄清和建议。

termios 结构在 Swift 中被视为结构,这并不奇怪,但令人惊讶的是结构中的控制字符数组现在是一个元组。我原以为它只是一个数组。正如你可能想象的那样,我花了一段时间才弄清楚这一点。如果我在游乐场工作:

var settings:termios = termios()
print(settings)

然后我会打印该结构的正确详细信息。

在 Obj-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

相反,但似乎找不到任何描述 termios 的 Swift“版本”的文档。有谁知道元组是否为其元素预先分配了名称,或者如果没有,是否有办法在事后分配名称?我应该使用命名元素创建自己的元组,然后将其分配给

settings.c_cc
吗?

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

print(VMIN)
print(VTIME)

然后打印正确的值并且不会产生编译器错误。我有兴趣对此进行任何澄清或评论。这是一个错误吗?

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

cfsetspeed
的定义为

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

speed_t
被类型定义为无符号长整型。在 Obj-C 中我们会这样做

cfsetspeed(&settings, B38400);

但是由于

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

macos swift swift2 termios
2个回答
3
投票

让我们从第二个问题开始,这个问题更容易解决。

B38400
is 在 Swift 中可用,只是类型错误。 所以你必须明确地转换它:

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

据我所知,你的第一个问题没有“好的”解决方案。 固定大小的数组作为元组导入到 Swift 中,并且据我所知,您不能使用 variable 来寻址元组元素。

但是,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
}
© www.soinside.com 2019 - 2024. All rights reserved.