Author: Amaury Forgeot d'Arc <amaur...@gmail.com> Branch: Changeset: r78101:dad26a9f1b29 Date: 2015-06-14 23:48 +0200 http://bitbucket.org/pypy/pypy/changeset/dad26a9f1b29/
Log: Tkinter: Add support for bignum numbers. diff --git a/lib_pypy/_tkinter/app.py b/lib_pypy/_tkinter/app.py --- a/lib_pypy/_tkinter/app.py +++ b/lib_pypy/_tkinter/app.py @@ -141,6 +141,7 @@ Tcl_AppInit(self) # EnableEventHook() + self._typeCache.add_extra_types(self) return self def __del__(self): diff --git a/lib_pypy/_tkinter/tclobj.py b/lib_pypy/_tkinter/tclobj.py --- a/lib_pypy/_tkinter/tclobj.py +++ b/lib_pypy/_tkinter/tclobj.py @@ -1,6 +1,7 @@ # TclObject, conversions with Python objects from .tklib_cffi import ffi as tkffi, lib as tklib +import binascii class TypeCache(object): def __init__(self): @@ -8,10 +9,18 @@ self.ByteArrayType = tklib.Tcl_GetObjType("bytearray") self.DoubleType = tklib.Tcl_GetObjType("double") self.IntType = tklib.Tcl_GetObjType("int") + self.BigNumType = None self.ListType = tklib.Tcl_GetObjType("list") self.ProcBodyType = tklib.Tcl_GetObjType("procbody") self.StringType = tklib.Tcl_GetObjType("string") + def add_extra_types(self, app): + # Some types are not registered in Tcl. + result = app.call('expr', '2**63') + typePtr = AsObj(result).typePtr + if tkffi.string(typePtr.name) == "bignum": + self.BigNumType = typePtr + def FromTclString(s): # If the result contains any bytes with the top bit set, it's @@ -30,6 +39,24 @@ return s +# Only when tklib.HAVE_LIBTOMMATH! +def FromBignumObj(app, value): + bigValue = tkffi.new("mp_int*") + if tklib.Tcl_GetBignumFromObj(app.interp, value, bigValue) != tklib.TCL_OK: + app.raiseTclError() + try: + numBytes = tklib.mp_unsigned_bin_size(bigValue) + buf = tkffi.new("unsigned char[]", numBytes) + bufSize_ptr = tkffi.new("unsigned long*", numBytes) + if tklib.mp_to_unsigned_bin_n( + bigValue, buf, bufSize_ptr) != tklib.MP_OKAY: + raise MemoryError + bytes = tkffi.buffer(buf)[0:bufSize_ptr[0]] + sign = -1 if bigValue.sign == tklib.MP_NEG else 1 + return sign * int(binascii.hexlify(bytes), 16) + finally: + tklib.mp_clear(bigValue) + def FromObj(app, value): """Convert a TclObj pointer into a Python object.""" typeCache = app._typeCache @@ -37,17 +64,19 @@ buf = tkffi.buffer(value.bytes, value.length) return FromTclString(buf[:]) - elif value.typePtr == typeCache.BooleanType: + if value.typePtr == typeCache.BooleanType: return bool(value.internalRep.longValue) - elif value.typePtr == typeCache.ByteArrayType: + if value.typePtr == typeCache.ByteArrayType: size = tkffi.new('int*') data = tklib.Tcl_GetByteArrayFromObj(value, size) return tkffi.buffer(data, size[0])[:] - elif value.typePtr == typeCache.DoubleType: + if value.typePtr == typeCache.DoubleType: return value.internalRep.doubleValue - elif value.typePtr == typeCache.IntType: + if value.typePtr == typeCache.IntType: return value.internalRep.longValue - elif value.typePtr == typeCache.ListType: + if value.typePtr == typeCache.BigNumType and tklib.HAVE_LIBTOMMATH: + return FromBignumObj(app, value) + if value.typePtr == typeCache.ListType: size = tkffi.new('int*') status = tklib.Tcl_ListObjLength(app.interp, value, size) if status == tklib.TCL_ERROR: @@ -61,9 +90,9 @@ app.raiseTclError() result.append(FromObj(app, tcl_elem[0])) return tuple(result) - elif value.typePtr == typeCache.ProcBodyType: + if value.typePtr == typeCache.ProcBodyType: pass # fall through and return tcl object. - elif value.typePtr == typeCache.StringType: + if value.typePtr == typeCache.StringType: buf = tklib.Tcl_GetUnicode(value) length = tklib.Tcl_GetCharLength(value) buf = tkffi.buffer(tkffi.cast("char*", buf), length*2)[:] diff --git a/lib_pypy/_tkinter/tklib_build.py b/lib_pypy/_tkinter/tklib_build.py --- a/lib_pypy/_tkinter/tklib_build.py +++ b/lib_pypy/_tkinter/tklib_build.py @@ -46,14 +46,16 @@ TK_HEX_VERSION = config_lib.TK_HEX_VERSION -HAVE_LIBTOMMATH = ((0x08050208 <= TK_HEX_VERSION < 0x08060000) or - (0x08060200 <= TK_HEX_VERSION)) +HAVE_LIBTOMMATH = int((0x08050208 <= TK_HEX_VERSION < 0x08060000) or + (0x08060200 <= TK_HEX_VERSION)) tkffi = FFI() tkffi.cdef(""" char *get_tk_version(); char *get_tcl_version(); +#define HAVE_LIBTOMMATH ... + #define TCL_READABLE ... #define TCL_WRITABLE ... #define TCL_EXCEPTION ... @@ -162,13 +164,34 @@ void Tcl_FindExecutable(char *argv0); """) +if HAVE_LIBTOMMATH: + tkffi.cdef(""" +#define MP_OKAY ... +#define MP_NEG ... +typedef struct { + int sign; + ...; +} mp_int; + +int Tcl_GetBignumFromObj(Tcl_Interp *interp, Tcl_Obj *obj, mp_int *value); + +int mp_unsigned_bin_size(mp_int *a); +int mp_to_unsigned_bin_n(mp_int * a, unsigned char *b, unsigned long *outlen); +void mp_clear(mp_int *a); +""") + tkffi.set_source("_tkinter.tklib_cffi", """ +#define HAVE_LIBTOMMATH %(HAVE_LIBTOMMATH)s #include <tcl.h> #include <tk.h> +#if HAVE_LIBTOMMATH +#include <tclTomMath.h> +#endif + char *get_tk_version() { return TK_VERSION; } char *get_tcl_version() { return TCL_VERSION; } -""", +""" % globals(), include_dirs=incdirs, libraries=linklibs, library_dirs = libdirs _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit