rtea-proc 4.0.0

Internal macro crate for rtea.
Documentation
  • Coverage
  • 100%
    6 out of 6 items documented5 out of 6 items with examples
  • Size
  • Source code size: 19.53 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 301.57 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 9s Average build duration of successful builds.
  • all releases: 3s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • jrolli/rtea
    3 2 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • jrolli

rtea-proc

Procedural macros for writing Tcl extensions with rtea. These macros generate the extern "C" entry points that Tcl expects when loading or unloading an extension, handling interpreter validation and pointer casting so you do not have to.

This crate is re-exported by rtea and is not normally added as a direct dependency.

Macros

#[module_init(Name, "version")]

Generates Name_Init, the entry point Tcl calls when the extension is loaded with load or package require.

The macro wraps your function, validates the interpreter pointer, initialises the global stubs table, calls your function, and then registers the package version with Tcl. If your function returns Err, the message is set as the interpreter's error result and TclStatus::Error is returned to Tcl.

#[module_init(Example, "1.0.0")]
fn init(interp: &Interpreter) -> Result<TclStatus, String> {
    interp.create_command("hello", hello_cmd)
}

The version argument is optional; omit it to register the package without a version string.

#[module_safe_init(Name, "version")]

Generates Name_SafeInit, called by Tcl when loading the extension into a safe interpreter. Use this to register only the subset of commands that are safe for untrusted code. The function signature is identical to module_init.

#[module_safe_init(Example, "1.0.0")]
fn safe_init(interp: &Interpreter) -> Result<TclStatus, String> {
    interp.create_command("hello", hello_cmd)
}

#[module_unload(Name)]

Generates Name_Unload, called by Tcl when the extension is unloaded. The flags argument indicates whether only this interpreter is detaching (TclUnloadFlag::DetachFromInterpreter) or whether the library is being unmapped from the process entirely (TclUnloadFlag::DetachFromProcess).

#[module_unload(Example)]
fn unload(_interp: &Interpreter, _flags: TclUnloadFlag) -> Result<TclStatus, String> {
    Ok(TclStatus::Ok)
}

#[module_safe_unload(Name)]

Generates Name_SafeUnload, the counterpart to module_safe_init. Called when a safe interpreter that loaded the extension is torn down.

#[module_safe_unload(Example)]
fn safe_unload(_interp: &Interpreter, _flags: TclUnloadFlag) -> Result<TclStatus, String> {
    Ok(TclStatus::Ok)
}

#[derive(TclObjectType)]

Implements TclObjectType for a struct, registering it as a native Tcl object type. The struct must also implement Clone, Display, and Debug.

The generated implementation provides:

  • A static ObjectType descriptor recognised by Tcl's type system.
  • from_object(&Object) -> Option<&Self> — borrows the inner value from a Tcl object, converting from its string representation if needed.
  • into_object(self) -> Object — wraps the value in a new Tcl object.
  • A From<Self> for Object impl for convenience.
#[derive(Clone, Debug, TclObjectType)]
struct Point { x: f64, y: f64 }

impl std::fmt::Display for Point {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{} {}", self.x, self.y)
    }
}

Register the type with the interpreter before use:

interp.register_obj_type::<Point>();

Naming Conventions

Tcl requires extension entry points to follow the pattern Name_Init where Name has an uppercase first letter and all remaining letters lowercase. The macros enforce this by using the name exactly as written — ensure it matches the final library name (e.g. Example for libexample.so).