Design Notes for the new Tkinter C Interface
This note currently contains original design notes (scribbled on a palm pilot one warm day in San Jose), and has not been checked against the actual implementation.
March 2000 | Fredrik LundhTypes
The new C interface defines a number of object types:
Interpreter
This type holds a pointer to a Tcl interpreter instance. It should have the same layout as the corresponding object in the current version of Tkinter.
PyTclObject
This is a Python type implementation that wraps a Tcl object.
struct { TclObj* object; } PyTclObject;
To create new PyTclObject instances, call the factory function with an ordinary Python object:
PyString -> TclStringObj PyInt -> TclIntegerObj or TclStringObj (if too large) PyFloat -> TclFloatObj PyTuple -> TclArrayObj (?)
All other objects are converted to string objects (using PyObject_Str).
PyTclCommand
This type wraps a pointer to a Tcl command, and the associated client data.
struct { /* true if command uses object interface */ int use_obj_interface; /* command/client pointer */ TclCmd* command; void* client_data; } PyTclCommandObject;
The factory function takes a command name, and looks it up using Tcl’s CommandInfo function. Note that this type doesn’t provide any additional methods; at this time, it’s main purpose is to provide information for the bound method type.
PyTclBoundMethodObject
This is a callable type which combines a PyTclCommandObject with a method name (as a PyTclObject string) and information on how to convert arguments and results.
struct { PyTclCommandObject* command; PyTclObject* method; void* convert; /* to be defined */ } PyTclBoundMethodObject;
The call hook accepts an argument tuple and a keyword dictionary. The values in the tuple are converted to PyTclObject’s. Simplified:
def makeargs(av, kw): size = 1 + len(av) + 2*len(kw) argv = tuple(size) argv[0] = method i = 1 for v in av: if v is PyTclObject: argv[i] = v else: argv[i] = pytclobject(v) i = i + 1 for k, v in kw: argv[i] = "-" + k if item is PyTclObject: argv[i+1] = v else: argv[i+1] = pytclobject(v) i = i + 2 result = command->command(command->client_data, argv) return pytclobject(result)
To speed things up even further, we could use a dictionary mapping well-known option names to PyTclObject strings which *include* the leading hyphen.
New Tkinter Interface
The new Tkinter interface is data driven.
For each widget class, the interface uses a method table which is used by the getattr hook to create PyTclBoundMethod objects on the fly.
class Scale(Widget): _tk_map = { "get": (PyTclObject("get"), None), "set": (PyTclObject("set"), None), } __getattr__ = Widget._tk_getattr
Global String Cache
The global string cache maps known Tkinter names (method names, and common option values as defined in the Tkconstants module) to Tcl string objects (PyTclObject).