Tcl Source Code

View Ticket
Login
2023-04-16
15:36 Ticket [3bb3bcf2da] Adding support for 8.7/9.0 to Tcl.pm, Tkinter status still Open with 4 other changes artifact: c483acbf99 user: chrstphrchvz
2023-03-29
16:53 Ticket [3bb3bcf2da]: 3 changes artifact: 11cfccda5f user: jan.nijtmans
10:55 Ticket [3bb3bcf2da]: 3 changes artifact: c3199eae96 user: chrstphrchvz
2022-11-17
19:55 Ticket [3bb3bcf2da]: 3 changes artifact: 3463030d4b user: chrstphrchvz
2022-09-22
22:27 Ticket [3bb3bcf2da]: 3 changes artifact: 2cb97687dd user: chrstphrchvz
2022-09-06
07:12 Ticket [3bb3bcf2da]: 4 changes artifact: 0b662a2833 user: jan.nijtmans
04:41 Ticket [3bb3bcf2da]: 3 changes artifact: 3c993fef92 user: chrstphrchvz
04:40 New ticket [3bb3bcf2da]. artifact: 13ceb6c1d0 user: chrstphrchvz

Ticket UUID: 3bb3bcf2da5bfe20b1ab863fd2de940bd04f4aa
Title: Adding support for 8.7/9.0 to Tcl.pm, Tkinter
Type: Support Version: core-8-branch, trunk
Submitter: chrstphrchvz Created on: 2022-09-06 04:40:55
Subsystem: 10. Objects Assigned To: jan.nijtmans
Priority: 5 Medium Severity: Minor
Status: Open Last Modified: 2023-04-16 15:36:33
Resolution: None Closed By: nobody
    Closed on:
Description:

I would like to add support for Tcl 8.7/9.0 to Tcl.pm, a wrapper for using Tcl from Perl: https://github.com/gisle/tcl.pm/pull/42. My understanding is that it intends to remain compatible with Tcl 8.4.

The main difficulty I have encountered so far is updating its SvFromTclObj() function for converting a given Tcl value to a Perl value of similar type. (The fromObj() function in Python’s Tkinter serves a similar purpose.) It will need to accommodate types no longer being registered in newer Tcl; it seems the workaround is to create a Tcl_Obj * of the desired type and then get its typePtr, as mentioned in TIP 484, and already done in some cases by Tkinter.

One part I am still trying to understand is how to handle boolean types. This is complicated not only by some confusion on what the expected behavior on the Perl side is (e.g. https://github.com/gisle/tcl.pm/issues/47), but also by the various changes since Tcl 8.4. From what I can tell, Tcl so far has had a registered "boolean" type tclBooleanType added in 8.4, then renamed to oldBooleanType in 8.5, and dropped in 9.0 (and 8.7 with TCL_NO_DEPRECATED); and it has had an unregistered "booleanString" type tclBooleanType since 8.5, but which is now going to be called "boolean" in 9.0 (this was also the briefly the case for Tcl 8.7 with TCL_NO_DEPRECATED from [8b366f71d8] until being reverted seemingly without comment in 4f6d4a2b15). I am not aware why "booleanString" is being renamed to "boolean" other than it possibly seeming strange to have "booleanString" and no other boolean type present. Is there an issue that prevents it remaining "booleanString" for compatibility?

I would be curious if there is any further advice for adapting C library code for Tcl 8.7/9.0 not already given in TIPs 484/485/600, and if anyone is aware of examples I can refer to of older C code successfully updated for 8.7/9.0. TIP 484 mentions some affected programs, but those do not appear to be actively maintained. I am not aware of Tkinter already preparing for Tcl 8.7/9.0, and Ruby tcltk seems further behind (still contains handling for Tcl 8.3).

There are probably other things I should ask Tcl for help in this effort, though I’m not yet sure sure exactly what.

User Comments: chrstphrchvz added on 2023-04-16 15:36:33:

I am now looking into contributing similar changes to Tkinter: https://github.com/python/cpython/issues/103194

I am trying to understand how obsolete registered types in 8.7, i.e. "int" on 32-bit systems and Tcl 8.4 "boolean", should be handled. Even though Tcl itself will never create values with obsolete types, is there some case I am overlooking which requires wrappers to still be able to recognize values with these types? The only possibility I can think of is if some C code out there (e.g. extensions) tries to create values with these types anyway (by setting objPtr->typePtr to a Tcl_ObjType * obtained from Tcl_GetObjType() as well as manually setting objPtr->internalRep), even though such code is likely broken under 9.0.


jan.nijtmans added on 2023-03-29 16:53:42:

> Is it true that if a Tcl value is already of type "bytearray", then both Tcl_GetByteArrayFromObj() and Tcl_GetBytesFromObj() behave the same and do not return NULL?

Yes, that's true


chrstphrchvz added on 2023-03-29 10:55:32:

…I would still like to request that "booleanString" please not be renamed to "boolean" to avoid/reduce confusion for maintainers of existing code.

Tkinter being one affected example (although changing their code to use the idiom suggested here is likely still an option): https://github.com/python/cpython/blob/7559f5fda94a/Modules/_tkinter.c#L1201

I want to make sure I understand the relevance of TIP 568 to a wrapper. TIP 568 warns: “Most callers of Tcl_GetByteArrayFromObj are probably buggy”. But maybe the use case of a wrapper is an exception: it only ever wants to use Tcl_GetByteArrayFromObj() to retrieve values which are already of "bytearray" type. Is it true that if a Tcl value is already of type "bytearray", then both Tcl_GetByteArrayFromObj() and Tcl_GetBytesFromObj() behave the same and do not return NULL? It would be preferable to continue using Tcl_GetByteArrayFromObj() to maintain compatibility with 8.6 and earlier.


chrstphrchvz added on 2022-11-17 19:55:29:

Related: [b5bd08df8d61]


chrstphrchvz added on 2022-09-22 22:27:16:

Thanks for suggesting an approach for getting the boolean type. I get the impression one should not care what Tcl calls string (non-numeric) boolean values, but I would still like to request that "booleanString" please not be renamed to "boolean" to avoid/reduce confusion for maintainers of existing code.


jan.nijtmans added on 2022-09-06 07:12:10:

> One part I am still trying to understand is how to handle boolean types

Well, having a short look at the code, this won't work for your case:

    Tcl_NewBooleanObj(0);

The reason: this will create an integer object, not a boolean one. If you want a boolean, do:

    Tcl_Obj boolObj = Tcl_NewStringObj("true", );
    int value;
    Tcl_GetBooleanFromObj(NULL, boolObj, &value);

Then you can be sure that boolObj->typePtr will be the typePtr you want.

The reason for the change is that in Tcl 8.7, the boolean values is stored in internalRep->longValue, in Tcl 9.0 it's stored in internalRep->wideValue (making it the same as for integers). External code should not assume anything about the internal representation, but code that does should still work in Tcl 8.7. Using "Tcl_GetBooleanFromObj" should do the trick, without assuming anything about the internal representation of booleans.

Hope this helps! Feel free to ask more