Tcl_Method(3)

okay bestie, welcome to Tcl_Method(3) from the TclOO Library Functions ✨ this is the page where we learn how to manipulate methods and method-call contexts in TclOO. grab a strawberry πŸ“ and let's get into it.

🌸 NAME 🌸

The whole squad of functions on this page:

  • Tcl_ClassSetConstructor
  • Tcl_ClassSetDestructor
  • Tcl_MethodDeclarerClass
  • Tcl_MethodDeclarerObject
  • Tcl_MethodIsPublic
  • Tcl_MethodIsPrivate
  • Tcl_MethodIsType
  • Tcl_MethodIsType2
  • Tcl_MethodName
  • Tcl_NewInstanceMethod
  • Tcl_NewInstanceMethod2
  • Tcl_NewMethod
  • Tcl_NewMethod2
  • Tcl_ObjectContextInvokeNext
  • Tcl_ObjectContextIsFiltering
  • Tcl_ObjectContextMethod
  • Tcl_ObjectContextObject
  • Tcl_ObjectContextSkippedArgs

...and together they manipulate methods and method-call contexts. periodt. πŸ’…

✨ SYNOPSIS ✨

#include <tclOO.h>

Tcl_Method
Tcl_NewMethod(interp, class, nameObj, flags, methodTypePtr,
              clientData)

Tcl_Method
Tcl_NewMethod2(interp, class, nameObj, flags, methodType2Ptr,
               clientData)

Tcl_Method
Tcl_NewInstanceMethod(interp, object, nameObj, flags, methodTypePtr,
                      clientData)

Tcl_Method
Tcl_NewInstanceMethod2(interp, object, nameObj, flags, methodType2Ptr,
                       clientData)

Tcl_ClassSetConstructor(interp, class, method)

Tcl_ClassSetDestructor(interp, class, method)

Tcl_Class
Tcl_MethodDeclarerClass(method)

Tcl_Object
Tcl_MethodDeclarerObject(method)

Tcl_Obj *
Tcl_MethodName(method)

int
Tcl_MethodIsPublic(method)

int
Tcl_MethodIsPrivate(method)

int
Tcl_MethodIsType(method, methodTypePtr, clientDataPtr)

int
Tcl_MethodIsType2(method, methodType2Ptr, clientDataPtr)

int
Tcl_ObjectContextInvokeNext(interp, context, objc, objv, skip)

int
Tcl_ObjectContextIsFiltering(context)

Tcl_Method
Tcl_ObjectContextMethod(context)

Tcl_Object
Tcl_ObjectContextObject(context)

Tcl_Size
Tcl_ObjectContextSkippedArgs(context)

πŸŽ€ ARGUMENTS πŸŽ€

  • Tcl_Interp *interp (in/out) β€” the interpreter that's holding the object or class you wanna create or update a method in. πŸ’–
  • Tcl_Object object (in) β€” the object to create the method in.
  • Tcl_Class class (in) β€” the class to create the method in.
  • Tcl_Obj *nameObj (in) β€” the name of the method to create. It should not be NULL unless you're creating constructors or destructors.
  • int flags (in) β€” a flag saying (currently) what the visibility of the method is. The supported public values of this flag are TCL_OO_METHOD_PUBLIC (which is fixed at 1 for backward compatibility) for an exported method, TCL_OO_METHOD_UNEXPORTED (which is fixed at 0 for backward compatibility) for a non-exported method, and TCL_OO_METHOD_PRIVATE for a private method. πŸ‘‘
  • Tcl_MethodType *methodTypePtr (in) β€” a description of the type of the method to create, or the type of method to compare against.
  • Tcl_MethodType2 *methodType2Ptr (in) β€” a description of the type of the method to create, or the type of method to compare against.
  • void *clientData (in) β€” a piece of data that is passed to the implementation of the method without interpretation. no thoughts, just vibes. πŸ¦‹
  • void **clientDataPtr (out) β€” a pointer to a variable in which to write the clientData value supplied when the method was created. If NULL, the clientData value will not be retrieved.
  • Tcl_Method method (in) β€” a reference to a method to query.
  • Tcl_ObjectContext context (in) β€” a reference to a method-call context. Note that client code must not retain a reference to a context. πŸ’€
  • Tcl_Size objc (in) β€” the number of arguments to pass to the method implementation.
  • Tcl_Obj *const *objv (in) β€” an array of arguments to pass to the method implementation.
  • Tcl_Size skip (in) β€” the number of arguments passed to the method implementation that do not represent "real" arguments. iykyk.

πŸ’– DESCRIPTION πŸ’–

A method is an operation carried out on an object that is associated with the object. Every method must be attached to either an object or a class; methods attached to a class are associated with all instances (direct and indirect) of that class. periodt.

Given a method, the entity that declared it can be found using Tcl_MethodDeclarerClass, which returns the class that the method is attached to (or NULL if the method is not attached to any class), and Tcl_MethodDeclarerObject, which returns the object that the method is attached to (or NULL if the method is not attached to an object). The name of the method can be retrieved with Tcl_MethodName, whether the method is exported is retrieved with Tcl_MethodIsPublic, and whether the method is private is retrieved with Tcl_MethodIsPrivate. The type of the method can also be introspected upon to a limited degree; the function Tcl_MethodIsType returns whether a method is of a particular type, assigning the per-method clientData to the variable pointed to by clientDataPtr if (that is non-NULL) if the type is matched. Tcl_MethodIsType2 does the same for TCL_OO_METHOD_VERSION_2. πŸ’…

πŸ¦‹ METHOD CREATION πŸ¦‹

Methods are created by Tcl_NewMethod and Tcl_NewInstanceMethod, or by Tcl_NewMethod2 and Tcl_NewInstanceMethod2, which create a method attached to a class or an object respectively. In both cases, the nameObj argument gives the name of the method to create, the flags argument states whether the method should be exported initially or be marked as a private method, the methodTypePtr or methodType2Ptr (for TCL_OO_METHOD_VERSION_2) argument describes the implementation of the method (see the METHOD TYPES section below), and the clientData argument gives some implementation-specific data that is passed on to the implementation of the method when it is called. ✨

When the nameObj argument to Tcl_NewMethod or Tcl_NewMethod2 is NULL, an unnamed method is created, which is used for constructors and destructors. Constructors should be installed into their class using the Tcl_ClassSetConstructor function, and destructors (which must not require any arguments) should be installed into their class using the Tcl_ClassSetDestructor function. Unnamed methods should not be used for any other purpose, and named methods should not be used as either constructors or destructors. Also note that a NULL methodTypePtr or methodType2Ptr is used to provide internal signaling, and should not be used in client code. 😭

🧚 METHOD CALL CONTEXTS 🧚

When a method is called, a method-call context reference is passed in as one of the arguments to the implementation function. This context can be inspected to provide information about the caller, but should not be retained beyond the moment when the method call terminates. πŸ’€

The method that is being called can be retrieved from the context by using Tcl_ObjectContextMethod, and the object that caused the method to be invoked can be retrieved with Tcl_ObjectContextObject. The number of arguments that are to be skipped (e.g. the object name and method name in a normal method call) is read with Tcl_ObjectContextSkippedArgs, and the context can also report whether it is working as a filter for another method through Tcl_ObjectContextIsFiltering. 🌸

During the execution of a method, the method implementation may choose to invoke the stages of the method call chain that come after the current method implementation. This (the core of the next command) is done using Tcl_ObjectContextInvokeNext. Note that this function does not manipulate the call-frame stack, unlike the next command; if the method implementation has pushed one or more extra frames on the stack as part of its implementation, it is also responsible for temporarily popping those frames from the stack while the Tcl_ObjectContextInvokeNext function is executing. Note also that the method-call context is never deleted during the execution of this function. πŸ”₯


✨ METHOD TYPES ✨

Okay bestie, so the vibe of a method is described by a pointer to a Tcl_MethodType or Tcl_MethodType2 struct β€” the latter is for when you're living that TCL_OO_METHOD_VERSION_2 life. Here's what they look like, and yes, you're gonna wanna screenshot this:

typedef struct {
    int version;
    const char *name;
    Tcl_MethodCallProc *callProc;
    Tcl_MethodDeleteProc *deleteProc;
    Tcl_CloneProc *cloneProc;
} Tcl_MethodType;

typedef struct {
    int version;
    const char *name;
    Tcl_MethodCallProc2 *callProc;
    Tcl_MethodDeleteProc *deleteProc;
    Tcl_CloneProc *cloneProc;
} Tcl_MethodType2;

So the version field? She always needs to be set to TCL_OO_METHOD_VERSION_CURRENT, TCL_OO_METHOD_VERSION_1, or TCL_OO_METHOD_VERSION_2. No cap. The name field is just a human-readable lil label for the type β€” it's literally what you see when you run the info class methodtype and info object methodtype Tcl commands. Slay.

The callProc field is the function that gets called when the method is invoked. And bestie, it must never be NULL. Like, ever. 🚫

The deleteProc field is the function used to delete a particular method β€” it gets called when the method is replaced or removed. If it's NULL, then we just assume the method's clientData needs no special action to delete. Easy peasy.

And the cloneProc field? Either it's a function that copies a method's clientData (like when you're doing a Tcl_CopyObjectInstance), or it's NULL which means the clientData can just be copied directly. No drama.


πŸ’– TCL_METHODCALLPROC FUNCTION SIGNATURE πŸ’–

Functions that match this signature get called when the method is invoked. Here's the tea:

typedef int Tcl_MethodCallProc(
        void *clientData,
        Tcl_Interp *interp,
        Tcl_ObjectContext objectContext,
        int objc,
        Tcl_Obj *const *objv);

typedef int Tcl_MethodCallProc2(
        void *clientData,
        Tcl_Interp *interp,
        Tcl_ObjectContext objectContext,
        Tcl_Size objc,
        Tcl_Obj *const *objv);

So the clientData argument? That's the value you gave when the method was created. The interp is where you can execute scripts, access variables, and also where you put the result of the method. The objc and objv fields give you the parameter objects to the method. You can discover the calling context through the objectContext argument, and the return value from a Tcl_MethodCallProc is any Tcl return code (like TCL_OK, TCL_ERROR, etc.). Iconic.


🌸 TCL_METHODDELETEPROC FUNCTION SIGNATURE 🌸

These functions get used when a method is deleted β€” whether because a new method is being created or because the object or class is being deleted.

typedef void Tcl_MethodDeleteProc(
        void *clientData);

The clientData argument to a Tcl_MethodDeleteProc will be the exact same value you passed to the clientData argument of Tcl_NewMethod or Tcl_NewInstanceMethod when the method was created. Memory lane, but make it deletion.


πŸ¦‹ TCL_CLONEPROC FUNCTION SIGNATURE πŸ¦‹

These functions are used to copy a method when the object or class is copied using Tcl_CopyObjectInstance (or oo::copy).

typedef int Tcl_CloneProc(
        Tcl_Interp *interp,
        void *oldClientData,
        void **newClientDataPtr);

The interp argument gives you a place to write an error message if the clone attempt is gonna fail β€” and in that case, the clone procedure must also return TCL_ERROR. Otherwise, it should return TCL_OK. The oldClientData field gives the value from the method being copied from, and the newClientDataPtr field will point to a variable where you write the value for the method being copied to. Copy-paste but make it custom. ✨


πŸ‘‘ REFERENCE COUNT MANAGEMENT πŸ‘‘

Okay, this part is giving "adulting" but it's important, so pay attention.

  • The nameObj argument to Tcl_NewMethod and Tcl_NewInstanceMethod (when it's not NULL) will have its reference count incremented if there is no existing method with that name in that class or object. So like, don't be surprised.
  • The result of Tcl_MethodName is a value with a reference count of at least one. You should not modify it without first duplicating it (with Tcl_DuplicateObj). Respect the boundaries.
  • The values in the first objc values of the objv argument to Tcl_ObjectContextInvokeNext are assumed to have a reference count of at least 1; the containing array is assumed to endure until the next method implementation (see next) returns. Be aware that methods may yield β€” so if you want any post-call actions (like decrementing the reference count of values passed in here), you must schedule them with Tcl_NRAddCallback. No sneaky after-parties without scheduling.
  • The callProc of the Tcl_MethodType structure takes values of at least reference count 1 in its objv argument. It may add its own references, but it must not decrement the reference count below that level. The caller of the method will decrement the reference count once the method returns properly (and the reference will be held if the method yields). So don't touch what you didn't create, bestie. πŸ’…

🌈 SEE ALSO 🌈

  • Class(3)
  • NRE(3)
  • oo::class(n)
  • oo::define(n)
  • oo::object(n)

⭐ KEYWORDS ⭐

  • constructor
  • method
  • object

That's the whole vibe, bestie. This was TclOO version 0.1, page Tcl_Method(3) β€” go forth and write methods like the main character you are. πŸ’–βœ¨πŸŽ€

πŸ“¦ where this page comes from