[pypy-commit] pypy default: Tkinter: Add support for bignum numbers.
amauryfa
noreply at buildbot.pypy.org
Mon Jun 15 09:33:17 CEST 2015
Author: Amaury Forgeot d'Arc <amauryfa at 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
More information about the pypy-commit
mailing list