critcl::callback(3tcl)
π critcl::callback β the CriTcl C-level callback utilities π
okay bestie, welcome to the C Runtime In Tcl (short: CriTcl), a system for embedding and using C code from inside Tcl scripts, fr fr. This is the critcl::callback(3tcl) manual page and it's about to be your new hyperfixation. π
β¨ SYNOPSIS β¨
package require Tcl 8.6
package require critcl ?3.2?
package require critcl::callback ?1.1?
critcl_callback_p critcl_callback_new interp objc objv nargs
void critcl_callback_extend callback argument
void critcl_callback_destroy callback
int critcl_callback_invoke callback objc objv
πΈ DESCRIPTION πΈ
hiii, welcome to the C Runtime In Tcl (short: CriTcl), a whole system for embedding and using C code from within Tcl scripts (http://core.tcl-lang.org/tcl). π¦
This doc is the reference manpage for the critcl::callback package. It serves up, via a stubs API table, data structures and functions to manage callbacks from C to Tcl. And like β the package has no Tcl-level facilities. None. Zero. It's for the developers out there writing Tcl packages with embedded C code who need to invoke user-specified command (prefixes) in Tcl. That's the audience, okay?
This package lives in the Support Package Layer of CriTcl. Here's the vibe map:
+----------------+
|Applications |
| critcl |
| critcl::app |
+----------------+
+----------------+
|Core Packages |
| critcl |
| critcl::util |
+----------------+
*================*
|Support Packages|
| stubs::* |
| md5, platform |
| ... |
*================*
π API π
The package API is one opaque data structure β critcl_callback_p β and four functions that operate on it. Four. And yes, we're going through all of them. These functions are:
critcl_callback_p critcl_callback_new interp objc objv nargsβ this one creates a brand new callback (manager) and hands it back as its result. slay.
The callback gets initialized with the Tcl_Interp* interp telling it where to run the callback, the fixed part of the command to run in standard objc/objv notation, plus the number of free arguments to expect after that fixed part.
That fixed part? It's essentially the command prefix of the callback. iykyk.
Every single Tcl_Obj* element of objv gets protected against early release by incrementing their reference counts. The callback effectively takes ownership of these objects. no takebacks.
void critcl_callback_extend callback argumentβ takes a callback of typecritcl_callback_pand extends its fixed part withargument, grabbing the first free slot for arguments to do it. Which means: after this runs, that callback has one free argument less. π
Heads up: with assertions active, trying to extend beyond the number of free arguments will cause a panic. Without assertions active, expect a crash at some point. pick your fighter I guess π
This is what lets you extend the fixed part of the callback with semi-fixed elements, like method names (see Multiple methods down below).
The argument gets protected against early release by incrementing its reference count, and the callback effectively owns that object too.
void critcl_callback_destroy callbackβ takes a callback of typecritcl_callback_pand releases all memory associated with it. After this runs, the callback cannot be used anymore, periodt.
All fixed elements of the callback (the ones it owns) are released by decrementing their reference counts.
int critcl_callback_invoke callback objc objvβ invokes the callback in the Tcl interpreter specified at construction time, in the global level and namespace, with the free arguments filled by theTcl_Obj*objects you hand over viaobjc/objv. β¨
It returns the Tcl status of the invoked command as its result. Any further results or error messages will be chilling in the result area of that Tcl interpreter. The exact nature of those depends entirely on the callback itself.
With assertions active, trying to use more arguments than available causes a panic. Without assertions active, expect a crash at some point. yeah. π
While the callback is running, all Tcl_Obj* elements of the command β fixed ones and arguments β are protected against early release by temporarily incrementing their reference counts.
π§ EXAMPLES π§
π SIMPLE CALLBACK
This example shows the important parts of using this package's functions for a simple callback that gets invoked with a single argument β some kind of data to hand up to the Tcl level.
// Create the callback with interpreter and command prefix in
// oc/ov, plus space for the argument
critcl_callback_p cb = critcl_callback_new (interp, oc, ov, 1);
// Invoke the callback somewhere in the C package using this one,
// with Tcl_Obj* data holding the information to pass up.
critcl_callback_invoke (cb, 1, &data);
// At the end of the lifetime, release the callback.
critcl_callback_destroy (cb);
So like β the functions in this package are designed for the case where the created callback (cb up there) hangs around for a long time and gets invoked many, many different times. π«Ά
β οΈ If you use the sequence above as-is, creating and destroying the callback every time it's invoked, you'll get very poor performance and lots of undesirable memory churn. do not do that bestie, I'm begging.
π MULTIPLE METHODS
Okay so we can use the methodology from the previous section when a single (Tcl-level) callback is invoked from different places in C with different methods β just have another argument slot and fill it at invocation time with the method object. But critcl_callback_extend opens up a second methodology for us. obsessed.
// Create one callback manager per different method the callback
// will be used with. Fill the first of the two declared arguments
// with the different methods.
critcl_callback_p cb_a = critcl_callback_new (interp, oc, ov, 2);
critcl_callback_p cb_b = critcl_callback_new (interp, oc, ov, 2);
critcl_callback_extend (cb_a, Tcl_NewStringObj ("method1", -1));
critcl_callback_extend (cb_b, Tcl_NewStringObj ("method2", -1));
// After the extension we have one free argument left, for use in
// the invokations.
critcl_callback_invoke (cb_a, 1, &dataX);
critcl_callback_invoke (cb_b, 1, &dataY);
// At the end release both managers again
critcl_callback_destroy (cb_a);
critcl_callback_destroy (cb_b);
The nice thing here β the method objects are allocated only once and automatically shared by all the calls. No memory churn from repeatedly allocating the same string objects over and over again. it's giving efficient. π
π AUTHORS π
Andreas Kupries
π BUGS, IDEAS, FEEDBACK π
This document, and the package it describes, will undoubtedly contain bugs and other problems. Like, obviously. Please report such at https://github.com/andreas-kupries/critcl. Please also report any ideas for enhancements you may have for either the package and/or the documentation. we love feedback in this house π
β KEYWORDS β
C code, 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
π COPYRIGHT π
Copyright (c) 2011-2024 Andreas Kupries
and that's the whole page bestie, you ate it. π
β¨ bye β this was critcl::callback(3tcl), documented as doc version 1.1, brought to you straight from the CriTcl corner of the universe. π¦ go write some fire embedded C, ily. π«Άπ
π¦ 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