将正确的类型传递给 addch() [ncurses, Linux]

Passing the correct type to addch() [ncurses, Linux]

在遵循 tutorial 如何将 ncurses 与 swift 一起使用时,我遇到了错误:

main.swift:31:15: error: cannot convert value of type 'UInt?' to expected argument type 'chtype' (aka 'UInt32')
        addch(UInt("*"))
              ^~~~~~~~~

它抱怨类型,但是当我将其更改为 UInt32 时,错误更改为 error: ambiguous use of 'init' addch(UInt32("*"))

问题

完整代码供参考:

import Foundation
import CNCURSES
import Glibc

enum Signal:Int32 {
case INT   = 2
case WINCH = 28
}

typealias SignalHandler = __sighandler_t

func trap(signum:Signal, action:@escaping SignalHandler) {
  signal(signum.rawValue, action)
}

func getmaxyx(window:UnsafeMutablePointer<WINDOW>, y:inout Int32, x:inout Int32) {
  x = getmaxx(window)
  y = getmaxy(window)
}

func getcuryx(window:UnsafeMutablePointer<WINDOW>, y:inout Int32, x:inout Int32) {
  x = getcurx(window)
  y = getcury(window)
}

func drawbox(numlines:Int32, numcols:Int32) {
  for y in 0...numlines-1 {
    for x in 0...numcols {
      move(y, x)
      if y == 0 || y == numlines-1 {
        addch(UInt("*"))
      } else {
        if x == 0 || x == numcols {
          addch(UInt("*"))
        }
      }
    }
  }
  refresh()
}

[...]

initscr()
noecho()
curs_set(0)
getmaxyx(window:stdscr, y:&maxy, x:&maxx)
drawbox(numlines:maxy, numcols:maxx)
center(text:"Hello world!", numlines:maxy, numcols:maxx)

while true {
  select(0, nil, nil, nil, nil)
}

看到报错信息,需要传一个UInt32值给addch(_:)

UInt("*")的return类型为UInt?,其实际值始终为nil。 (简单的 StringUInt 转换试图将字符串解释为十进制整数。)

当你想要一个字符编码为UInt32时,你可能需要这样写:

addch(("*" as UnicodeScalar).value)

如果您的代码会有更多 addch(_:) 次调用,您可以为其定义一个简单的包装器。

例如:

func addCh(_ us: UnicodeScalar) {
    addch(us.value)
}

addCh("*")

通过显式注释为 UnicodeScalar,字符串文字被解释为 UnicodeScalar 并且其 value 属性 的类型为 UInt32.

正确的(和documented type)是chtype:

   int addch(const chtype ch);
   int waddch(WINDOW *win, const chtype ch);
   int mvaddch(int y, int x, const chtype ch);
   int mvwaddch(WINDOW *win, int y, int x, const chtype ch);
   int echochar(const chtype ch);
   int wechochar(WINDOW *win, const chtype ch);

chtype中的位数取决于系统。在 ncurses 的头文件中,它默认声明为 unsigned,但当 configuring/building ncurses.

时可以覆盖它。

X/Open(参见 addch and <curses.h>)没有比这更明确的了。

当然,无论它在 swift 中是什么,都是绑定的实现细节,除非有文档说明, 如有更改。