pyreadline-1.7.1に入れ替えたら、それまで動いていたWin32を呼ぶクリアスクリーンが動かなくなってしまった、という現象がありまして、その理由がわかりませんでした。にわか仕込みでデバッガ(pdb)を使ったりしましたがヤッパリわからない。
結局、次のエラーメッセージのとおりだったんですね。
File "./lib/win32cls.py", line 67, in clear_screen
coord, byref(dwDummy))
ArgumentError: argument 4:: wrong type
File "./lib/win32cls.py", line 67 は次のようなコード。
FillConsoleOutputAttribute (hConOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, byref(dwDummy))
FillConsoleOutputAttribute関数の第4引数(argument 4)は、coordですが、このcoordが実際に wrong type だったようです。X,Y座標を含むデータであるcoordの初期化は次のとおり。
coord = COORD() # 初期値 coord.X = 0, coord.Y = 0
COORDは、もともとはC言語の構造体ですが、それをPythonクラスとして定義しています。
class COORD(Structure): """struct in wincon.h.""" _fields_ = [ ("X", SHORT), ("Y", SHORT)]
このCOORD型データがWin32 API関数にうまく渡らないようです。それに気付いたのは、pyreadlineのconsole.pyのなかにfixcoordという関数を見つけたからです。必要な部分だけを抜き書きすると:
# pyreadline-1.7.1/pyreadline/console/cosole.py # # Copyright (C) 2003-2006 Gary Bishop. # Copyright (C) 2006 Jorgen Stenarson. <jorgen.stenarson@bostream.nu> # # Distributed under the terms of the BSD License. def fixcoord(x, y): u'''Return a long with x and y packed inside.''' # this is a hack! ctypes won't pass structures but COORD is # just like a long, so this works. return c_int(y << 16 | x)
座標を作るときは、例えば COORD(2, 3) の代わりに fixcoord(2, 3) とします。そうするとエラーはなくなります。
しかし不思議なのは、以前pyreadline-1.5と併用していたときはfixcoordなしで動いていたことです。pyreadline-1.5がWindows APIをフックするようなことは考えにくいし、pyreadline-1.5自体も逐一fixcoordしています。ウーン謎だ。