【问题标题】:Cross compiled ncurses for UTF-8 displays incorrectlyUTF-8 的交叉编译 ncurses 显示不正确
【发布时间】:2014-07-12 07:32:10
【问题描述】:

我有一个嵌入式系统,带有一个 vt52u(unicode)终端仿真器,它可以正确显示 UTF-8 字符,但我有交叉编译的程序(vim 和 python)在使用 ncursesw 时无法在该终端上正确显示 unicode 字符图书馆。

我已经进行了搜索,但网络上似乎没有任何可用的帮助...

Bash shell 设置了以下变量:

LANG=en_US.UTF-8
LD_LIBRARY_PATH=/mnt/sd/lib  # all libraries, cross compiled, are located here
TERM=vt52u
TERMCAP='vt52u|vt52 with UTF-8:am:eo:rs=\Ee\Eb0\Eco:is=\EE\Ee:nl=^j:sr=\Ei:bl=^g:ta=^i:ho=\EH:cr=^m:le=\ED:nd=\EC:do=\EB:up=\EA:ta=^i:nw=^m:xn:cm=\EY%+ %+ :it#8:co#75:li#24:sc=\Ej:rc=\Ek:vi=\Ef:ve=\Ee:so=\Eb0\Ec4:se=\Eb0\Eco:mh=\Eb8\Eco:mr=\Ebo\Ec0:me=\Eb0\Eco:cl=\EH\EJ:cd=\EJ:ce=\EK:km:ku=^p:kd=^n:kr=^f:kl=^b:kb=^h:'
LOCALE=

而且我知道 unicode 终端很好,因为我可以运行以下程序让它完美地显示 UTF-8 字符。

#!/bin/env python
#coding=UTF-8

charset = [
0x2205, 0x2629, 0x00B2, 0x2663, 0x2666, 0x00B1, 0x221A, 0x266B,
0x2190, 0x2524, 0x2500, 0x2534, 0x253C, 0x251C, 0x2193, 0x2191,
0x00B0, 0x2665, 0x00AE, 0x2660, 0x00B7, 0x00A4, 0x00A4, 0x00A4,
0x00D7, 0x00B5, 0x2126, 0x252C, 0x250C, 0x2510, 0x2514, 0x2518
]

for i in charset:
    print unichr( i ).encode("UTF-8"),
    if i == 0x2191: print
print


bash-4.3#./testunicode
bash-4.3# ∅ ☩ ² ♣ ♦ ± √ ♫ ← ┤ ─ ┴ ┼ ├ ↓ ↑
bash-4.3# ° ♥ ® ♠ · ¤ ¤ ¤ × µ Ω ┬ ┌ ┐ └ ┘

但是当我尝试在 python 程序中使用 curses (ncursesw) 显示方框图字符,或使用 vim(链接到 ncursesw)编辑 UTF-8 文本文件时;我最终在屏幕上打印了一个无效的 unicode 框,然后是额外的符号,如 ~T~B、~T~L,以及每个 unicode 字符的许多其他变体。所以,出于某种原因,ncursesw 正在输出无效的 UTF-8 字符....

我知道它的链接是正确的,并且没有冲突的 ncurses 库;只有 ncursesw 存在。

我为编译配置了 ncurses-5.9 库,如下所示:

./configure --prefix=/mnt/sd --without-cxx --without-cxx-binding --without-ada --without-manpages --without-progs --without-tests --without-curses-h --with-build-cc=gcc --with-shared --without-normal --without-debug --without-profile --without-gpm --without-dlsym --without-sysmouse --build=i686-linux --host=arm-linux-gnueabi --without-pthread --enable-widec --with-fallbacks=vt52 --with-terminfo-dirs=/etc/terminfo --disable-big-core --enable-termcap --with-termpath=/Data/termcap

例如:以下程序在我的桌面 linux ~VT102 上运行良好——但在 vt52u 上运行时在嵌入式系统上出现故障:

#!/bin/env python
# coding=UTF-8
board=[
"","",
u"   ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐",
u"   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │   │",
u"   │   │ ├───→───→───→ │   │   │   │   │   │ ├───→───→───→ │   │   │" ]

board = ( i.encode("utf-8") for i in board )

import curses
import locale
locale.setlocale( locale.LC_ALL,"" )

screen = curses.initscr()
curses.noecho() # no echoing
curses.cbreak() # no keyboard buffering

# Setup the playing board screen. 
for i,s in enumerate( board ): screen.addstr( i,0,s )
screen.refresh()

import time
time.sleep(2)

# Return everything to normal
curses.echo()
curses.nocbreak()
curses.endwin()

编辑:我发现了该错误的一个可能原因——glibc,被交叉编译,没有到 /mnt/sd/share/i18n/charmap 或 /mnt/sd/share/i18n/locales 的正确路径目录。它只有部分路径以错误的“/”为前缀,而不是目标系统的实际根路径 /mnt/sd。当没有找到文件时,glibc 显然默认回到“C”或“POSIX”语言环境并忽略环境变量。

我不确定是否必须重新编译glibc并手动编辑makefile,或者是否有办法在系统构建后手动设置路径....??有任何想法吗。 ???

【问题讨论】:

  • 您是否尝试将示例移植到 Python 3?使用 3 的文本模型的情况可能会有所不同。 Python Mailing List也有一些这方面能力过强的人,你可以去那里问问。
  • 不,尽管我可能会在下周晚些时候尝试。我知道错误出在 NCURSES 上,因为我使用 Python 还是“C”程序都没有关系;他们都失败了。您可以通过将上述 python 测试程序中的语言环境变量设置为“C”来模拟正在运行的 Linux xterm 或控制台终端上的故障。这会产生我在嵌入式系统上看到的“~T~L”符号,并以几乎相同的方式使显示出现乱码;所以我倾向于认为问题出在语言环境变量......或标准 C 库。
  • 等等,“VT52U”?这是一回事?!
  • :) 是的!它是。你想要源代码吗?它在 linux 帧缓冲区上绘制 ascii 字体并模拟 DEC VT52,但具有 unicode UTF-8 解码能力。它的主要目的是成为电子纸设备上的控制台,如 arm 处理器下的索尼 PRS-900 (E-Brook)。
  • 错字:那是 innsbrook,就像用于电子墨水电子纸显示器的宽幅 linux 内核驱动程序一样。对不起。

标签: python vim unicode utf-8 ncurses


【解决方案1】:

Ncurses 依赖于标准 C 库,该库需要编译路径到包含国际化文件的目录,否则 NCURSES 将自动默认回到 POSIX 语言环境(也称为“C”语言环境)并且不会执行 UTF -8。

在语言环境存储在与主机不同的位置的构建系统上进行交叉编译可能会导致自动配置脚本错误识别目录,然后嵌入式系统将无法执行 UTF-8,即使语言环境变量是设置正确......更糟糕的是,失败可能不会生成任何错误消息。

但是:如果路径错误,那么在运行时您将无法看到除 POSIX 和 C 之外的任何语言环境:

locale -a

在构建系统上使用国际化文件设置一个虚拟目录,然后重新编译标准 C 库是解决问题的一种方法;但它可能需要 root 权限。

另外,使用gnu标准C库(glibc)时可以设置一个环境变量“I18NPATH”;它应该覆盖编译的路径。如果嵌入式系统上的安装前缀是“/mnt/sd”,那么从 bash shell -- 只需:

export I18NPATH="/mnt/sd/share/i18n"

在任何一种情况下,一旦正确的路径可用/安装 - 系统应该正常运行。如果没有,请检查以确保已为国家/地区charmap 和UTF-8 的组合实际生成了区域设置,这是所需的(使用“locale -a”将它们全部列出)。

如果它不存在,可以使用“localedef”实用程序非常简单地创建它。例如:要创建支持 UTF-8 的美国英语语言环境,只需执行以下操作:

localedef -i en_US -c -f UTF-8 en_US.UTF-8

然后,确保设置并导出语言环境变量:

export LOCALE=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8

然后运行不带参数的语言环境应该将所有变量显示为 en_US.UTF-8 ... 从那时起一切都会正常工作。

【讨论】:

    猜你喜欢
    • 2012-04-12
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 2012-12-26
    • 2015-12-26
    • 2023-04-02
    • 2011-08-09
    相关资源
    最近更新 更多