critcl::class(3tcl)
π NAME π
okay so critcl::class(3tcl) β that's the manual page name, bestie, and honestly the whole thing lives under the CriTcl umbrella. CriTcl stands for C Runtime In Tcl, and this particular lovely is all about Code Gen for C Classes. β¨
π SYNOPSIS π
package require Tcl 8.6
package require critcl ?3.2?
package require critcl::class ?1.1?
::critcl::class::define name script
include path
support code
type name
classconstructor body
classdestructor body
constructor body ?postbody?
destructor body
classvariable ctype name ?comment? ?constructor? ?destructor?
classmethod name command arguments body
classmethod name proc arguments resulttype body
classmethod name as funname ?arg...?
insvariable ctype name ?comment? ?constructor? ?destructor?
method name command arguments body
method name proc arguments resulttype body
method name as funname ?arg...?
method_introspection
πΈ DESCRIPTION πΈ
hiii, welcome to the C Runtime In Tcl (short and cute: CriTcl) β it's a whole system for embedding and using C code from right inside your Tcl scripts. The Tcl we're talking about lives over at [http://core.tcl-lang.org/tcl](http://core.tcl-lang.org/tcl), iykyk. π
This document right here is the reference manpage for the critcl::class package. And what does that package do? It hands you convenience commands for advanced functionality, all built on top of the core. It's giving wrapper energy, but the good kind. π«Ά
So here's the vibe: say you want a C level object that comes with class and instance commands. With this package you get to just concentrate on specifying the class- and instance-variables and the class- and instance-methods, in a manner that's lowkey similar to a TclOO class π β and meanwhile all the necessary boilerplate around it is managed by this package. Not you. You're free. You're the main character. π
Who's this for? Mainly developers wishing to write Tcl packages with embedded C code. That's the audience, fr fr.
This package resides in the Core Package Layer of CriTcl, which looks like this:
+----------------+
|Applications |
| critcl |
| critcl::app |
+----------------+
*================*
|Core Packages |
| critcl |
| critcl::util |
*================*
+----------------+
|Support Packages|
| stubs::* |
| md5, platform |
| ... |
+----------------+
π οΈ API π οΈ
::critcl::class::definename script β this is THE main command, the one you came for. It defines a new class called name, where name is the name of the Tcl command representing the class, i.e. the class command. The script is where the specification of the class goes β included headers, class- and instance variables, class- and instance methods, all of it. Want the detailed list of available commands and what they actually mean? Scroll on down to the Class Specification API section below, bestie. π
π CLASS SPECIFICATION API π
Here's where we document every single class specification command you can use inside that script argument of ::critcl::class::define. Let's gooo. π
βοΈ GENERAL CONFIGURATION βοΈ
includepath β tells it the path of a header file to include within the code generated for the class. Now, this is separate fromsupportbecause the generated include directives get put at the very beginning of the generated code. Why? So you can use the imported declarations within the instance type, and elsewhere. Makes sense, right? β¨ Calls to this command are cumulative. And yes, you're totally allowed to not use it at all if your class isn't making use of external definitions. The result is the empty string. Clean. πsupportcode β this one specifies supporting C code, i.e. any definitions (types, functions, etc.) that the whole class needs but that don't fit into the class- and instance-methods. The code gets embedded at global level, outside of any function or other definition. Calls are cumulative again, and again you can just skip it entirely if your class doesn't need supporting code. Result of the command is the empty string. πtypename β specifies the name of an external C type to be used as the type of the instance structure. Heads up though: initialization and release of the structure with the given type are the responsibility of the user, done through constructor and destructor code fragments. π
β οΈ ATTENTION bestie: using this command precludes the use of regular class- and instance variables. It further precludes the use of method-introspection as well, because that makes use of generated instance-variables. So like, pick your path. π
If class- and/or instance-variables have to be used in conjunction with an external C type, simply create and use a class- or instance-variable with that type. Boom, solved. π¦
The result of the command is the empty string.
π CLASS LIFETIME MANAGEMENT π
classconstructorbody β specifies a C code block surrounding the initialization of the class variables, i.e. the fields of the class structure. Just so we're clear: allocation and release of the class structure itself is done by the system, and is not the responsibility of the user. π«Ά
For the initialization (and release) of a class variable, it's recommended that you use the constructor and destructor arguments of that variable's definition instead of writing a separate classconstructor (see the classvariable command). β¨
This is an optional command. Using it more than once is allowed too, and each use will add another C code fragment to use during construction β i.e. multiple calls aggregate.
The C code blocks of multiple calls (including the constructors of classvariable definitions) are executed in order of specification. Periodt.
The result of the command is the empty string.
The C code in body has access to the following environment:
interpβ Pointer to the Tcl interpreter (Tcl_Interp*) the class structure will be associated with. It enables the generation of a Tcl error message should construction fail.classβ Pointer to the class structure to initialize.errorβ A C code label the constructor can jump to should it have to signal a construction failure. It is the responsibility of the constructor to release any variables already initialized before jumping to this label. This is also why the "execution in order of specification" thing is documented and can be relied on β it gives us the knowledge of which other constructors have already been run and initialized what other fields. π
classdestructorbody β specifies a C code block surrounding the release of the class variables, i.e. the fields of the class structure. And same as before: allocation and release of the class structure itself is done by the system, not the responsibility of the user. π
For the initialization (and release) of a class variable it's recommended to use the constructor and destructor arguments of the variable's definition (see command classvariable) instead of a separate classconstructor.
This is an optional command. Using it more than once is allowed too, and each use will add another C code fragment to use during construction. Multiple calls aggregate. β¨
The C code blocks of multiple calls (including the constructors of class variable definitions) are executed in order of specification.
The result of the command is the empty string.
The C code in body has access to the same environment as the class constructor code blocks. (Yeah, same three friends: interp, class, error. π)
π± INSTANCE LIFETIME MANAGEMENT π±
constructorbody ?postbody? β specifies a C code block surrounding the initialization of the instance variables, i.e. the fields of the instance structure. π
Note that allocation and release of the instance structure itself is done by the system and not the responsibility of the user. On the other hand, if an external type was specified for the instance structure, then instance variables are not possible, and the system has no knowledge of the type's structure β and in that case it is the responsibility of the body to allocate and free the structure itself too. So like, no pressure. π
For the initialization (and release) of an instance variable it's recommended to use the constructor and destructor arguments of the variable's definition (see command insvariable) instead of a separate constructor.
This is an optional command. Using it more than once is allowed too, and each use will add another C code fragment to use during construction. Multiple calls aggregate.
The C code blocks of multiple calls (including the constructors of instance variable definitions) are executed in order of specification.
The result of the command is the empty string.
The C code in body has access to the following environment:
interpβ Pointer to the Tcl interpreter (Tcl_Interp*) the instance structure will be associated with. It enables the generation of a Tcl error message should construction fail.instanceβ Pointer to the instance structure to initialize.errorβ A C code label the constructor can jump to should it have to signal a construction failure. It is the responsibility of the constructor to release any variables already initialized before jumping to this label. This is also why the "execution in order of specification" is documented and can be relied on β it gives us the knowledge of which other constructors have already been run and initialized what other fields. π
Now, the C code in postbody is responsible for construction actions to be done after the primary construction was done, and after the Tcl-level instance command was successfully created. It gets a slightly different environment: π¦
interpβ Pointer to the Tcl interpreter (Tcl_Interp*) the instance structure will be associated with. It enables the generation of a Tcl error message should construction fail.instanceβ Pointer to the instance structure to initialize.cmdβ TheTcl_Commandtoken of the Tcl-level instance command.fqnβ The fully qualified name of the instance command, stored in aTcl_Obj*.
destructor body π
okay so bestie, this command hands you a C code block that wraps around the release of the instance variables, aka the fields of the instance structure. πΈ
Real talk though: allocating and releasing the instance structure itself is the system's job, and it is not the user's responsibility. Don't touch it. π« But plot twist β if an external type was specified for the instance structure, then instance variables aren't possible at all, and the system has no knowledge of what that type's structure looks like. In that case it genuinely is on the body to allocate and free the structure itself too. π
For the initialization (and the release) of an instance variable, the rec is: use the constructor and destructor arguments of that variable's own definition instead of rolling a separate constructor β see the command insvariable for the deets. π«Ά
This command is optional. Using it more than once is allowed too, and each use just adds another C code fragment into the pile used during construction. Multiple calls aggregate, periodt. π
The C code blocks of multiple calls β including the constructors from instance variable definitions β are executed in order of specification. β
The result of the command is the empty string.
The C code in body has access to this environment:
instanceβ pointer to the instance structure to release.
β¨ CLASS VARIABLES AND METHODS β¨
classvariable ctype name ?comment? ?constructor? ?destructor?
This one declares a field in the class structure of the class. You can spec multiple fields, and they get saved in the order you specified them. π
Attention: spec'ing a class variable precludes the use of an external C type for the instance structure.
Attention: spec'ing a class variable automatically causes the definition of an instance variable named class, pointing to the class structure. π
Beyond the basic name and C ctype of the new variable, the definition can also carry a comment describing it, plus C code blocks to initialize and release the variable. Those two are effectively local forms of the commands classconstructor and classdestructor. Please go read their descriptions for all the details about the C environment available to the code. π
The comment, if you give one, will be embedded into the generated C code so cross-referencing from the generated .c file back to the class specification is way easier. π
classmethod name command arguments body
Alright bestie, this command specifies a class method plus the C code block that implements its functionality. This is form 1 of 3. π The method gets specified like a critcl::ccommand, with a fixed set of C-level arguments, and the body has to do everything itself β argument extraction, checking, returning the result, and obviously the actual functionality. No hand-holding, no wrapper. π€
For that, the body has access to:
classβ pointer to the class structure.interpβ pointer to the Tcl interpreter (Tcl_Interp*) the class structure is associated with.objcβ the number of method arguments.objvβ the method arguments, as C array ofTcl_Objpointers.
The arguments of the definition are only a human readable form of the method arguments and syntax, and they are not used in the C code at all β except as comments put into the generated code. Again: it is the responsibility of the body to check the number of arguments, extract them, check their types, etc. π
classmethod name proc arguments resulttype body
Here it is β form 2 of 3. β¨ This command specifies a class method and the C code block implementing its functionality, and the method gets specified like a critcl::cproc. π
Contrary to the first variant, here the arguments are computer readable, expected to be in the same format as the arguments of critcl::cproc. Same deal for the resulttype. The system will automatically generate a wrapper that does argument checking and conversion, plus result conversion β just like for critcl::cproc. π
The body has access to:
classβ pointer to the class structure.interpβ pointer to the Tcl interpreter (Tcl_Interp*) the class structure is associated with....β all arguments under their specified names and C types as per their definition.
classmethod name as funname ?arg...?
And form 3 of 3, the last one. π This command specifies a class method and the C code block implementing its functionality.
The class method is implemented by the external function funname, i.e. a function which is declared outside of the class code itself, or in a support block. π§
It is assumed that the first four arguments of that function represent the parameters:
classβ pointer to the class structure.interpβ pointer to the Tcl interpreter (Tcl_Interp*) the class structure is associated with.objcβ the number of method arguments.objvβ the method arguments, as C array ofTcl_Objpointers.
Any additional arg... specified will be added after those, and are passed into the C code as is, i.e. they are considered to be C expressions. π¦
π INSTANCE VARIABLES AND METHODS π
insvariable ctype name ?comment? ?constructor? ?destructor?
This one declares a field in the instance structure of the class. Multiple fields? Sure! They get saved in the order you specified them. π
Attention: spec'ing an instance variable precludes the use of an external C type for the instance structure.
Attention: spec'ing an instance variable automatically causes the definition of an instance variable of typeTcl_Command, namedcmd, holding the token of the instance command β and the definition of an instance method nameddestroy. This implicit instance variable is managed by the system, so hands off. π
Beyond the basic name and C ctype of the new variable, the definition can also carry a comment describing it, plus C code blocks to initialize and release the variable. These are effectively local forms of the commands constructor and destructor. Please read their descriptions for the deets on the C environment available to the code. π
The comment, if you give one, will be embedded into the generated C code so cross-referencing from the generated .c file back to the class specification is easy peasy. π
method name command arguments body
This command specifies an instance method and the C code block implementing its functionality. It's form 1 of 3! π The method is specified like a critcl::ccommand, with a fixed set of C-level arguments, and the body has to handle everything on its own β argument extraction, checking, result return, and of course the actual functionality. π€
For that, the body has access to:
instanceβ pointer to the instance structure.interpβ pointer to the Tcl interpreter (Tcl_Interp*) the instance structure is associated with.objcβ the number of method arguments.objvβ the method arguments, as C array ofTcl_Objpointers.
The arguments of the definition are only a human readable form of the method arguments and syntax β they are not used in the C code, except as comments put into the generated code. Again: the body is the one checking the number of arguments, extracting them, checking their types, etc. π
method name proc arguments resulttype body
Form 2 of 3, bestie. β¨ This command specifies an instance method and the C code block implementing its functionality, and the method is specified like a critcl::cproc. π
Contrary to the first variant, here the arguments are computer readable and expected to be in the same format as the arguments of critcl::cproc. Same thing for resulttype. The system automatically generates a wrapper that does argument checking and conversion, plus result conversion, like for critcl::cproc. π
The body has access to:
instanceβ pointer to the instance structure.interpβ pointer to the Tcl interpreter (Tcl_Interp*) the instance structure is associated with....β all arguments under their specified names and C types as per their definition.
method name as funname ?arg...?
Form 3 of 3, the final one. π This command specifies an instance method and the C code block implementing its functionality.
The instance method is implemented by the external function funname, i.e. a function which is declared outside of the instance code itself, or in a support block. π§
It is assumed that the first four arguments of that function represent the parameters:
instanceβ pointer to the instance structure.interpβ pointer to the Tcl interpreter (Tcl_Interp*) the instance structure is associated with.objcβ the number of method arguments.objvβ the method arguments, as C array ofTcl_Objpointers.
Any additional arg... specified will be added after those, and are passed into the C code as is, i.e. they are considered to be C expressions. π¦
method_introspection
This command generates one class-method and one instance-method, and both of them will return a list of the instance methods of the class β plus supporting structures, like the function that computes the information, and a class variable that caches it. π§ β¨
The two methods and the class variable are all named methods. π
π¦ CONTEXT DEPENDENT INTERACTIONS π¦
This section documents the various interactions between the specification commands. They're all documented with their individual commands, yeah, but here they're pulled together so you can see it all at a glance. π
- If you are using the command
typeto specify an external C type to use for the instance structure, you are subject to the following constraints and rules:- [1] You cannot define your own instance variables. π ββοΈ
- [2] You cannot define your own class variables. π ββοΈ
- [3] You cannot use
method_introspection. π ββοΈ
iykyk, external types come with rules and the rules are non-negotiable, bestie. π
so picking up the constraint list right where we left off, bestie: π
[4]β you have to allocate and release the instance structure on your own, through constructor and destructor code blocks. like, no hand-holding here. π[2]β if you declare class variables you are subject to the following constraints and rules:[1]β you cannot usetype. π«[2]β the system generates an instance variableclassfor you, which points from instance to class structure. This makes you also subject to the rules below, for instance variables.
[3]β if you declare instance variables (possibly automatic, see above) you are subject to following constraints and rules:[1]β you cannot usetype. π[2]β the system generates and manages an instance variablecmdfor you, which holds theTcl_Commandtoken of the instance command.[3]β the system generates an instance methoddestroyfor you.[4]β the system manages allocation and release of the instance structure for you. you have to care only about the instance variables themselves. periodt.
β¨ EXAMPLE β¨
okay so the example below is the specification of a queue data structure, with most of the method implementations and support code omitted to keep the size down. The full implementation can be found in the directory examples/queue of the critcl source distribution/repository. it's giving iconic. π¦
package require Tcl 8.6
package require critcl 3.2
critcl::buildrequirement {
package require critcl::class ; # DSL, easy spec of Tcl class/object commands.
}
critcl::cheaders util.h
critcl::class::define ::queuec {
include util.h
insvariable Tcl_Obj* unget {
List object unget elements
} {
instance->unget = Tcl_NewListObj (0,NULL);
Tcl_IncrRefCount (instance->unget);
} {
Tcl_DecrRefCount (instance->unget);
}
insvariable Tcl_Obj* queue {
List object holding the main queue
} {
instance->queue = Tcl_NewListObj (0,NULL);
Tcl_IncrRefCount (instance->queue);
} {
Tcl_DecrRefCount (instance->queue);
}
insvariable Tcl_Obj* append {
List object holding new elements
} {
instance->append = Tcl_NewListObj (0,NULL);
Tcl_IncrRefCount (instance->append);
} {
Tcl_DecrRefCount (instance->append);
}
insvariable int at {
Index of next element to return from the main queue
} {
instance->at = 0;
}
support {... queue_peekget, queue_size, etc.}
method clear {} {...}
method destroy {...}
method get as queue_peekget 1
method peek as queue_peekget 0
method put {item ...}
method size {} {
if ((objc != 2)) {
Tcl_WrongNumArgs (interp, 2, objv, NULL);
return TCL_ERROR;
}
Tcl_SetObjResult (interp, Tcl_NewIntObj (queue_size (instance, NULL, NULL, NULL)));
return TCL_OK;
}
method unget {item} {...}
}
package provide queuec 1
π AUTHORS π
Andreas Kupries β the icon, the legend, the moment. π
π BUGS, IDEAS, FEEDBACK π
This document, and the package it describes, will undoubtedly contain bugs and other problems. Please report such at https://github.com/andreas-kupries/critcl. Please also report any ideas for enhancements you may have for either package and/or documentation. no cap, we want all the tea. π«Ά
π KEYWORDS π
C class, C code, C instance, C object, Embedded C Code, code generator, compile & run, compiler, dynamic code generation, dynamic compilation, generate package, linker, on demand compilation, on-the-fly compilation β¨
π§ CATEGORY π§
Glueing/Embedded C code β periodt.
π COPYRIGHT π
Copyright (c) 2011-2024 Andreas Kupries
this page? fuelled by source doc, version 1.1 β and the date? not even in this footer, but the vibe is forever. byeee bestie π
π
π¦ where this page comes from
- ubuntu resolute: critcl 3.3.1+dfsg-1build1 Β· BSD
- ubuntu stonking: critcl 3.3.1+dfsg-1.1 Β· BSD
- Copyright (c) 2011-2024 Andreas Kupries
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms