How to correctly rename Tcl commands defined in c

101 Views Asked by At

I defined a tcl command in c++

Tcl_CreateObjCommand(interp, "myproc", myproc_func, nullptr, nullptr);

in tclsh

% rename myproc newproc

in C code

myproc_func(ClientData clientData,Tcl_Interp *interp,int objc,Tcl_Obj *const objv[])

at this moment when I run

% newproc

It will call myproc's function, which is myproc_func, but at this time myproc_func's objv[0]->bytes corresponds to the name "newproc", which causes me to fail in looking for the function corresponding to the function name named newproc.

Is it possible to map commands after rename to commands before in tcl?

2

There are 2 best solutions below

0
Punit Gajjar On

In Tcl, once you use the rename command to change the name of a procedure or command, you cannot directly remap the new name back to the original name of the command. The rename command effectively changes the name of the command in the interpreter's namespace, and it doesn't create a new mapping from the new name to the old name.

In your scenario, you initially registered a command named "myproc" with C++ code, and then you used rename to change it to "newproc." After this renaming, you cannot directly map "newproc" back to "myproc" within Tcl.

However, you can work around this by creating a wrapper procedure or alias that calls the renamed command. Here's how you can do it:

proc myproc_wrapper {args} {
    # You can perform any pre-processing here if needed
    # ...

    # Call the renamed command (newproc)
    uplevel newproc $args

    # You can perform any post-processing here if needed
    # ...
}

# Now, when you call myproc_wrapper, it will call newproc

In the code above, we define a myproc_wrapper procedure that takes any number of arguments (args) and then uses uplevel to execute the renamed command "newproc" with those arguments. You can add any pre-processing or post-processing as needed within the wrapper.

This way, you can effectively achieve the behavior of calling the original "myproc" even though it was renamed to "newproc."

Let me know if this helps.

0
Donal Fellows On

If you want to get a handle to an existing command that persists through renames, you should use Tcl_GetCommandFromObj() to get an opaque Tcl_Command handle (it's also returned by Tcl_CreateCommand() and Tcl_CreateObjCommand()). Renames do not alter that handle; they affect the process of going from the command name to the handle. You can get the current name of the command from the handle. (You can't invoke it directly through the handle though; that's not a public API we ever made. The internal API is tangled up in execution trace processing, so we don't expose that or even use it much ourselves outside of the implementation of the public API that is Tcl_EvalObjv() and its internal analog TclEvalObjv().)

Note that if you do this, you should set a delete trace on the command so that you know when to stop holding on to the handle.

There is no equivalent to the Tcl_Command handle in the Tcl script level API at all. The concept is not exposed.


The Tcl_Command is actually a pointer to a structure that contains the sort of information you can retrieve with Tcl_GetCommandInfoFromToken() as well as flags and pointers into various hash tables, trace tracking info, etc, but you should pretend you don't know about that. The internals of that are not part of the API at all, and may be subject to being changed between point releases of Tcl without notice.