GeezerVison is showing github.com — Tkinter: incompatible pointer types warnings when built with Tcl 9 · Issue #112672 · python/cpython
Tkinter: incompatible pointer types warnings when built with Tcl 9 #112672DescriptionTcl/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.
Linked PRs
Reacted by Ned Deily and Serhiy Storchaka Activitychrstphrchvz commented on Dec 8, 2023 ContributorAuthor More actions
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
There is ongoing debate upstream about what is actually needed here, most recently in https://sourceforge.net/p/tcl/mailman/tcl-core/thread/74564788-7d69-4c42-9205-c5f3e6a1409d%40elmicron.de/
Some want Tcl_Size to be a macro and not a typedef. Some do not want to force downstream projects/users to need “boilerplate” for 8.6 compatibility. Others do not care about Tcl/Tk < 9.0 and will gladly pass the buck downstream. serhiy-storchaka commented on Jun 4, 2024 In future we may change more code to support longer data in Python->Tcl conversion. But this requires testing, because not always the library supports larger than 2GiB data even if the size type is 64-bit (for example SQLite has 32-bit limitation even in its 64-bit API),
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|