Description
Tcl/Tk 9 changes C APIs to use a different type for sizes to allow transferring ≥32-bit sized things. The new type is Tcl_Size
, which as of TIP 660 is defined as either ptrdiff_t
in Tcl 9, or int
in Tcl 8.7 for binary compatibility.
My impression is that Tcl/Tk wrappers such as Tkinter, which are primarily used for Tk GUI, have little if any need for this. But as of TIP 664, usage of APIs which previously expected int *
must be updated for Tcl 9. There was previously effort in Tcl to continue allowing int *
usage for compatibility, and maybe that would have been good enough for Tkinter, but others in the Tcl/Tk inner circle (who already wish to abandon Tcl/Tk < 9 entirely) rejected that approach. -Wincompatible-pointer-types
warnings now seen under Tcl 9:
./Modules/_tkinter.c:504:21: warning: incompatible pointer types passing 'int *' to parameter of type 'Tcl_Size *' (aka 'long *') [-Wincompatible-pointer-types]
504 | const char *s = Tcl_GetStringFromObj(value, &len);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tcl90/include/tclDecls.h:4235:36: note: expanded from macro 'Tcl_GetStringFromObj'
4235 | (Tcl_GetStringFromObj)((objPtr), (sizePtr)))
| ^~~~~~~~~
tcl90/include/tclDecls.h:1754:15: note: passing argument to parameter 'lengthPtr' here
1754 | Tcl_Size *lengthPtr);
| ^
./Modules/_tkinter.c:1138:29: warning: incompatible pointer types passing 'int *' to parameter of type 'Tcl_Size *' (aka 'long *') [-Wincompatible-pointer-types]
1138 | char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tcl90/include/tclDecls.h:4229:41: note: expanded from macro 'Tcl_GetByteArrayFromObj'
4229 | (Tcl_GetBytesFromObj)(NULL, (objPtr), (sizePtr)))
| ^~~~~~~~~
tcl90/include/tclDecls.h:1751:32: note: passing argument to parameter 'numBytesPtr' here
1751 | Tcl_Obj *objPtr, Tcl_Size *numBytesPtr);
| ^
./Modules/_tkinter.c:1168:18: warning: incompatible pointer types passing 'int *' to parameter of type 'Tcl_Size *' (aka 'long *') [-Wincompatible-pointer-types]
1168 | status = Tcl_ListObjLength(interp, value, &size);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tcl90/include/tclDecls.h:4244:44: note: expanded from macro 'Tcl_ListObjLength'
4244 | (Tcl_ListObjLength)((interp), (listPtr), (lengthPtr)))
| ^~~~~~~~~~~
tcl90/include/tclDecls.h:1790:33: note: passing argument to parameter 'lengthPtr' here
1790 | Tcl_Obj *listPtr, Tcl_Size *lengthPtr);
| ^
./Modules/_tkinter.c:2104:13: warning: incompatible pointer types passing 'int *' to parameter of type 'Tcl_Size *' (aka 'long *') [-Wincompatible-pointer-types]
2104 | if (Tcl_ListObjGetElements(Tkapp_Interp(self),
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2105 | ((PyTclObject*)arg)->value,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
2106 | &objc, &objv) == TCL_ERROR) {
| ~~~~~~~~~~~~~
tcl90/include/tclDecls.h:4241:49: note: expanded from macro 'Tcl_ListObjGetElements'
4241 | (Tcl_ListObjGetElements)((interp), (listPtr), (objcPtr), (objvPtr)))
| ^~~~~~~~~
tcl90/include/tclDecls.h:1786:33: note: passing argument to parameter 'objcPtr' here
1786 | Tcl_Obj *listPtr, Tcl_Size *objcPtr,
| ^
./Modules/_tkinter.c:2136:9: warning: incompatible pointer types passing 'int *' to parameter of type 'Tcl_Size *' (aka 'long *') [-Wincompatible-pointer-types]
2136 | if (Tcl_SplitList(Tkapp_Interp(self), list,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2137 | &argc, &argv) == TCL_ERROR) {
| ~~~~~~~~~~~~~
tcl90/include/tclDecls.h:4250:40: note: expanded from macro 'Tcl_SplitList'
4250 | (Tcl_SplitList)((interp), (listStr), (argcPtr), (argvPtr)))
| ^~~~~~~~~
tcl90/include/tclDecls.h:1796:36: note: passing argument to parameter 'argcPtr' here
1796 | const char *listStr, Tcl_Size *argcPtr,
| ^
5 warnings generated.
Code intending to remain compatible with Tcl 8.6 is suggested to use the following after including tcl.h:
#ifndef TCL_SIZE_MAX
typedef int Tcl_Size;
# define Tcl_GetSizeIntFromObj Tcl_GetIntFromObj
# define Tcl_NewSizeIntObj Tcl_NewIntObj
# define TCL_SIZE_MAX INT_MAX
# define TCL_SIZE_MODIFIER ""
#endif
I intend to open a PR updating _tkinter.c to pass Tcl_Size *
where needed.
There are several other instances where Tkinter assumes Tcl expectsint
or something not larger than INT_MAX
, but migrating those to Tcl_Size
and TCL_SIZE_MAX
seems optional.