Tcl_ObjType(3)
β¨ NAME β¨
okay so bestie, this is Tcl_ObjType(3) from the Tcl Library Procedures β and it's giving βmanipulate Tcl value typesβ energy, periodt. π
These are the functions in the group chat:
Tcl_RegisterObjTypeTcl_GetObjTypeTcl_AppendAllObjTypesTcl_ConvertToTypeTcl_FreeInternalRepTcl_InitStringRepTcl_HasStringRepTcl_StoreInternalRepTcl_FetchInternalRep
and together they manipulate Tcl value types. π
π SYNOPSIS π
#include <tcl.h>
Tcl_RegisterObjType(typePtr)
const Tcl_ObjType *
Tcl_GetObjType(typeName)
int
Tcl_AppendAllObjTypes(interp, objPtr)
int
Tcl_ConvertToType(interp, objPtr, typePtr)
void
Tcl_FreeInternalRep(objPtr)
char *
Tcl_InitStringRep(objPtr, bytes, numBytes)
int
Tcl_HasStringRep(objPtr)
void
Tcl_StoreInternalRep(objPtr, typePtr, irPtr)
Tcl_ObjInternalRep *
Tcl_FetchInternalRep(objPtr, typePtr)
π ARGUMENTS π
const Tcl_ObjType *typePtr(in) β points to the structure containing information about the Tcl value type. This storage must live forever, typically by being statically allocated.const char *typeName(in) β the name of a Tcl value type thatTcl_GetObjTypeshould look up.Tcl_Interp *interp(in) β interpreter to use for error reporting.Tcl_Obj *objPtr(in) β forTcl_AppendAllObjTypes, this points to the value onto which it appends the name of each value type as a list element. ForTcl_ConvertToType, this points to a value that must have been the result of a previous call toTcl_NewObj.const char* bytes(in) β string representation.unsigned int numBytes(in) β length of the string representation in bytes.const Tcl_ObjInternalRep* irPtr(in) β internal object representation.const Tcl_ObjType* typePtr(in) β requested internal representation type.
bestie, yes, typePtr shows up twice in the argument list β first as the storage that must live forever, and last as the requested internal rep type. Keep both vibes. π«Ά
πΈ DESCRIPTION πΈ
The procedures in this man page manage Tcl value types (sometimes referred to as object types or Tcl_ObjTypes for historical reasons). They're used to register new value types, look up types, and force conversions from one type to another. β¨
Tcl_RegisterObjTypeβ okay so this one puts a new Tcl value type into the table of all value types thatTcl_GetObjTypecan look up by name. There are other value types supported by Tcl as well, which Tcl chooses not to register. Extensions can likewise choose to register the value types they create or not. The argumenttypePtrpoints to aTcl_ObjTypestructure that describes the new type by giving its name and by supplying pointers to four procedures that implement the type. If the type table already contains a type with the same name as intypePtr, it is replaced with the new type. TheTcl_ObjTypestructure is described in the section THE TCL_OBJTYPE STRUCTURE below.Tcl_GetObjTypeβ returns a pointer to the registeredTcl_ObjTypewith nametypeName. It returnsNULLif no type with that name is registered. πTcl_AppendAllObjTypesβ appends the name of each registered value type as a list element onto the Tcl value referenced byobjPtr. The return value isTCL_OKunless there was an error convertingobjPtrto a list value; in that caseTCL_ERRORis returned.Tcl_ConvertToTypeβ converts a value from one type to another if possible. It creates a new internal representation forobjPtrappropriate for the target typetypePtrand sets itstypePtrmember as determined by calling thetypePtr->setFromAnyProcroutine. Any internal representation forobjPtr's old type is freed. If an error occurs during conversion, it returnsTCL_ERRORand leaves an error message in the result value forinterpunlessinterpisNULL. Otherwise, it returnsTCL_OK. Passing aNULLinterpallows this procedure to be used as a test whether the conversion can be done (and in fact was done).
In many cases, thetypePtr->setFromAnyProcroutine will setobjPtr->typePtrto the argument valuetypePtr, but that is no longer guaranteed. ThesetFromAnyProcis free to set the internal representation forobjPtrto make use of another relatedTcl_ObjType, if it sees fit. π
Tcl_FreeInternalRepβ performs the function of the existing internal macroTclInitStringRep, but is extended to return a pointer to the string rep, and to acceptNULLas a value forbytes. WhenbytesisNULLandobjPtrhas no string rep, an uninitialzed buffer ofnumBytesbytes is created for filling by the caller. WhenbytesisNULLandobjPtrhas a string rep, the string rep will be truncated to a length ofnumBytesbytes. WhennumBytesis greater than zero, and the returned pointer isNULL, that indicates a failure to allocate memory for the string representation. The caller may then choose whether to raise an error or panic.Tcl_InitStringRepβ performs the function of the existing internal macroTclInitStringRep, but is extended to return a pointer to the string rep, and to acceptNULLas a value forbytes. WhenbytesisNULLandobjPtrhas no string rep, an uninitialzed buffer ofnumBytesbytes is created for filling by the caller. WhenbytesisNULLandobjPtrhas a string rep, the string rep will be truncated to a length ofnumBytesbytes. WhennumBytesis greater than zero, and the returned pointer isNULL, that indicates a failure to allocate memory for the string representation. The caller may then choose whether to raise an error or panic.Tcl_HasStringRepβ returns a boolean indicating whether or not a string rep is currently stored inobjPtr. This is used when the caller wants to act onobjPtrdifferently depending on whether or not it is a pure value. Typically this only makes sense in an extension if it is already known thatobjPtrpossesses an internal type that is managed by the extension.Tcl_StoreInternalRepβ stores inobjPtra copy of the internal representation pointed to byirPtrand sets its type totypePtr. WhenirPtrisNULL, this leavesobjPtrwithout a representation for typetypePtr.Tcl_FetchInternalRepβ returns a pointer to the internal representation stored inobjPtrthat matches the requested typetypePtr. If no such internal representation is inobjPtr, returnNULL.
And then there's the public type moment:
typedef union Tcl_ObjInternalRep {...} Tcl_ObjInternalRep
where the contents are exactly the existing contents of the union in the internalRep field of the Tcl_Obj struct. This definition permits us to pass internal representations and pointers to them as arguments and results in public routines. π
π¦ THE TCL_OBJTYPE STRUCTURE π¦
okay bestie, so if you're an extension writer and you wanna define new value types, you do it by defining four to twelve procedures and initializing a Tcl_ObjType structure to describe the type. You can also pass a pointer to your Tcl_ObjType structure to Tcl_RegisterObjType if you want to let other extensions look up your Tcl_ObjType by name with the Tcl_GetObjType routine. The Tcl_ObjType structure is defined like this:
typedef struct {
const char *name;
Tcl_FreeInternalRepProc *freeIntRepProc;
Tcl_DupInternalRepProc *dupIntRepProc;
Tcl_UpdateStringProc *updateStringProc;
Tcl_SetFromAnyProc *setFromAnyProc;
size_t version;
/* List emulation functions - ObjType Version 1 & 2 */
Tcl_ObjTypeLengthProc *lengthProc;
/* List emulation functions - ObjType Version 2 */
Tcl_ObjTypeIndexProc *indexProc;
Tcl_ObjTypeSliceProc *sliceProc;
Tcl_ObjTypeReverseProc *reverseProc;
Tcl_ObjTypeGetElements *getElementsProc;
Tcl_ObjTypeSetElement *setElementProc;
Tcl_ObjTypeReplaceProc *replaceProc;
Tcl_ObjTypeInOperatorProc *inOperProc;
} Tcl_ObjType;
β¨ THE NAME FIELD β¨
The name member is literally the name of the type, like int. When a type is registered, this is the name that callers of Tcl_GetObjType use to look it up. For unregistered types, the name field is mainly for debugging vibes. The remaining four members are pointers to procedures that the generic Tcl value code calls:
π THE SETFROMANYPROC FIELD π
The setFromAnyProc member contains the address of a function called to create a valid internal representation from a value's string representation.
typedef int Tcl_SetFromAnyProc(
Tcl_Interp *interp,
Tcl_Obj *objPtr);
If an internal representation cannot be created from the string, it returns TCL_ERROR and puts a message describing the error in the result value for interp unless interp is NULL. If setFromAnyProc is successful, it stores the new internal representation, sets objPtr's typePtr member to point to the Tcl_ObjType struct corresponding to the new internal representation, and returns TCL_OK. Before setting the new internal representation, the setFromAnyProc must free any internal representation of objPtr's old type; it does this by calling the old type's freeIntRepProc if it is not NULL.
As an example, the setFromAnyProc for the built-in Tcl list type gets an up-to-date string representation for objPtr by calling Tcl_GetStringFromObj. It parses the string to verify it is in a valid list format and to obtain each element value in the list, and, if this succeeds, stores the list elements in objPtr's internal representation and sets objPtr's typePtr member to point to the list type's Tcl_ObjType structure.
Do not release objPtr's old internal representation unless you replace it with a new one or reset the typePtr member to NULL.
The setFromAnyProc member may be set to NULL, if the routines making use of the internal representation have no need to derive that internal representation from an arbitrary string value. However, in this case, passing a pointer to the type to Tcl_ConvertToType will lead to a panic, so to avoid this possibility, the type should not be registered.
β οΈ panic warning: if you setsetFromAnyProctoNULLand still register,Tcl_ConvertToTypecan panic. just don't register it, bestie.
πΈ THE UPDATESTRINGPROC FIELD πΈ
The updateStringProc member contains the address of a function called to create a valid string representation from a value's internal representation.
typedef void Tcl_UpdateStringProc(
Tcl_Obj *objPtr);
objPtr's bytes member is always NULL when it is called. It must always set bytes non-NULL before returning. We require the string representation's byte array to have a null after the last byte, at offset length, and to have no null bytes before that; this allows string representations to be treated as conventional null character-terminated C strings. These restrictions are easily met by using Tcl's internal UTF encoding for the string representation, same as one would do for other Tcl routines accepting string values as arguments. Storage for the byte array must be allocated in the heap by Tcl_Alloc. Note that updateStringProcs must allocate enough storage for the string's bytes and the terminating null byte.
The updateStringProc for Tcl's built-in double type, for example, calls Tcl_PrintDouble to write to a buffer of size TCL_DOUBLE_SPACE, then allocates and copies the string representation to just enough space to hold it. A pointer to the allocated space is stored in the bytes member.
The updateStringProc member may be set to NULL, if the routines making use of the internal representation are written so that the string representation is never invalidated. Failure to meet this obligation will lead to panics or crashes when Tcl_GetStringFromObj or other similar routines ask for the string representation.
π no cap: if you setupdateStringProctoNULLand your string rep gets invalidated, it's panic/crash city whenTcl_GetStringFromObjor similar asks for the string. so don't do that unless you're 100% sure.
π¦ THE DUPINTREPPROC FIELD π¦
The dupIntRepProc member contains the address of a function called to copy an internal representation from one value to another.
typedef void Tcl_DupInternalRepProc(
Tcl_Obj *srcPtr,
Tcl_Obj *dupPtr);
dupPtr's internal representation is made a copy of srcPtr's internal representation. Before the call, srcPtr's internal representation is valid and dupPtr's is not. srcPtr's value type determines what copying its internal representation means.
For example, the dupIntRepProc for the Tcl integer type simply copies an integer. The built-in list type's dupIntRepProc uses a far more sophisticated scheme to continue sharing storage as much as it reasonably can.
π THE FREEINTREPPROC FIELD π
The freeIntRepProc member contains the address of a function that is called when a value is freed.
typedef void Tcl_FreeInternalRepProc(
Tcl_Obj *objPtr);
The freeIntRepProc function can deallocate the storage for the value's internal representation and do other type-specific processing necessary when a value is freed.
For example, the list type's freeIntRepProc respects the storage sharing scheme established by the dupIntRepProc so that it only frees storage when the last value sharing it is being freed.
The freeIntRepProc member can be set to NULL to indicate that the internal representation does not require freeing. The freeIntRepProc implementation must not access the bytes member of the value, since Tcl makes its own internal uses of that field during value deletion. The defined tasks for the freeIntRepProc have no need to consult the bytes member.
Note that if a subsidiary value has its reference count reduced to zero during the running of a freeIntRepProc, that value may be not freed immediately, in order to limit stack usage. However, the value will be freed before the outermost current Tcl_DecrRefCount returns.
β THE VERSION FIELD β
The version member provides for future extensibility of the structure and should be set to TCL_OBJTYPE_V0 for compatibility of ObjType definitions prior to version 9.0. Specifics about versions will be described further in the sections below.
β¨ ABSTRACT LIST TYPES β¨
okay so here's where it gets spicy πΆοΈ β the Tcl_ObjType descriptor has extra fields that let you control how custom data values get manipulated by Tcl's List commands without ever converting the value into a List type. iconic behavior, honestly.
For this to work, your custom type has to hand over functions that perform the given operation right on the custom data representation. Not all functions are required tho π«Ά. If a particular function is missing (i.e. it's set to NULL), the fallback is that the internal List operation just does the thing itself β which will most likely cause the value type to get converted into a traditional list. so like, yk, no free lunch π.
πΈ SCALAR VALUE TYPES πΈ
If your custom value type is scalar or atomic in nature β meaning it is not a divisible collection β then bestie, version TCL_OBJTYPE_V1 is what you want, fr fr.
In that case, List commands will treat the scalar value as if it were a list of length 1, and they will not convert the value into a List type. cute, right? π
π VERSION 2: ABSTRACT LISTS π
Version 2, a.k.a. TCL_OBJTYPE_V2, gives you full List support when you provide all the functions described down below β¬οΈ. This is the one that lets scripts use the List commands at script level without causing the type of the Tcl_Obj value to be converted to a list. main character energy π.
π¦ THE LENGTHPROC FIELD π¦
The LengthProc function is the bestie of the Tcl_ListObjLength C API. It returns the number of elements in the list. It gets used in every List operation and it is required for all Abstract List implementations β no skipping this one, okay? π€
typedef Tcl_Size
(Tcl_ObjTypeLengthProc) (Tcl_Obj *listPtr);
π THE INDEXPROC FIELD π
The IndexProc function correlates with the Tcl_ListObjIndex C API. It returns a Tcl_Obj value for the element sitting at the specified index. π―
typedef int (Tcl_ObjTypeIndexProc) (
Tcl_Interp *interp,
Tcl_Obj *listPtr,
Tcl_Size index,
Tcl_Obj** elemObj);
π§ THE SLICEPROC FIELD π§
The SliceProc correlates with the lrange command β it returns a new List or Abstract List for the portion of the original list you specified. slice it, serve it βοΈβ¨
typedef int (Tcl_ObjTypeSliceProc) (
Tcl_Interp *interp,
Tcl_Obj *listPtr,
Tcl_Size fromIdx,
Tcl_Size toIdx,
Tcl_Obj **newObjPtr);
π₯ THE REVERSEPROC FIELD π₯
The ReverseProc correlates with the lreverse command. It returns a List or Abstract List that has the same elements as the input Abstract List, just with the elements in reverse order. back it up, back it up π
typedef int (Tcl_ObjTypeReverseProc) (
Tcl_Interp *interp,
Tcl_Obj *listPtr,
Tcl_Obj **newObjPtr);
π THE GETELEMENTS FIELD π
The GetElements function returns a count and a pointer to an array of Tcl_Obj values for the entire Abstract List. This correlates to the Tcl_ListObjGetElements C API call. give me everything π«΄
typedef int (Tcl_ObjTypeGetElements) (
Tcl_Interp *interp,
Tcl_Obj *listPtr,
Tcl_Size *objcptr,
Tcl_Obj ***objvptr);
π THE SETELEMENT FIELD π
The SetElement function replaces the element within the specified list at the given index. This function correlates to the lset command. swap it out, slay π
typedef Tcl_Obj *(Tcl_ObjTypeSetElement) (
Tcl_Interp *interp,
Tcl_Obj *listPtr,
Tcl_Size indexCount,
Tcl_Obj *const indexArray[],
Tcl_Obj *valueObj);
π REPLACEPROC FIELD π
The ReplaceProc returns a new list after modifying the list β it replaces the elements to be deleted, and adds the elements to be inserted. This function correlates to the Tcl_ListObjReplace C API. out with the old, in with the new ποΈβ‘οΈβ¨
typedef int (Tcl_ObjTypeReplaceProc) (
Tcl_Interp *interp,
Tcl_Obj *listObj,
Tcl_Size first,
Tcl_Size numToDelete,
Tcl_Size numToInsert,
Tcl_Obj *const insertObjs[]);
π THE INOPERPROC FIELD π
The InOperProc function figures out whether the value is present in the given list, according to equivalent string comparison of elements. The boolResult gets set to 1 (true) if the value is present, and 0 (false) if it is not present. This function implements the in and ni math operators for an abstract list. are you in or are you out π
typedef int (Tcl_ObjTypeInOperatorProc) (
Tcl_Interp *interp,
Tcl_Obj *valueObj,
Tcl_Obj *listObj,
int *boolResult);
π«Ά REFERENCE COUNT MANAGEMENT π«Ά
okay bestie, this part is important, pay attention π
The objPtr argument to Tcl_AppendAllObjTypes should be an unshared value. This function will not modify the reference count of that value, but it will modify its contents. And if objPtr is not (interpretable as) a list, this function will set the interpreter result and produce an error β so using an unshared empty value is strongly recommended πΈ.
The objPtr argument to Tcl_ConvertToType can have any non-zero reference count. This function will not modify the reference count, but it may write to the interpreter result on error, so values that originate from there should have an additional reference made before calling this. noted πβ¨
None of the callback functions in the Tcl_ObjType structure should modify the reference count of their arguments β but if the values contain subsidiary values (like, say, the elements of a list or the keys of a dictionary), then those subsidiary values may have their reference counts modified. iykyk π
β SEE ALSO β
π KEYWORDS π
internal representation, value, value type, string representation, type conversion
and that's a wrap on the whole page, bestie πβ¨ this came from the Tcl source, version 9.0, and it's the Tcl_ObjType(3) page β go forth and build your abstract lists, you absolute icon ππ
π¦ where this page comes from
- alpine 3.23: tcl9-doc 9.0.3-r0 Β· TCL
- alpine 3.24: tcl9-doc 9.0.3-r2 Β· TCL
- fedora 43: tcl-doc 1:9.0.2-1.fc43 Β· TCL AND GPL-3.0-or-later WITH Bison-exception-2.2 AND BSD-3-Clause
- fedora 44: tcl-doc 1:9.0.2-1.fc44 Β· TCL AND GPL-3.0-or-later WITH Bison-exception-2.2 AND BSD-3-Clause
- nixos 26.05: tcl 9.0.3
- Copyright (c) 1996-1997 Sun Microsystems, Inc
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms