Reputation: 21514
I run a Tcl script from a C++ program using Tcl_EvalFile
. I defined some custom commands (using Tcl_CreateCommand
), so when they are found in the file a callback is called and then I can run some C++ code (TclInvokeStringCommand
invokes the callback given to Tcl_CreateCommand
, the callback type is int (*executeCmd)( ClientData data, Tcl_Interp *interp, int argc, const char *argv[] )
).
I want to know the script file name and line number within the callback function being invoked.
I could get the script file name using ((Interp*) interp)->scriptFile
.
However, I could not get the script file line number. Is there a way to retrieve this (or compute it in any way)?
Upvotes: 1
Views: 350
Reputation: 137587
The information is only exposed at the Tcl level via the info frame
command. (The internal C API for it is sufficiently horrible that it's never been made public.) This means you need to do something like this with Tcl_Eval()
:
// These can be cached safely per thread; reference management is a thing for another question
Tcl_Obj *scriptNameHandle = Tcl_NewStringObj("file", -1);
Tcl_Obj *lineNumberHandle = Tcl_NewStringObj("line", -1);
// How to actually get the information; I'm omitting error handling
Tcl_Eval(interp, "info frame -1");
Tcl_Obj *frameDict = Tcl_GetObjResult(interp);
Tcl_Obj *scriptNameObj = nullptr, *lineNumberObj = nullptr;
Tcl_DictObjGet(nullptr, frameDict, scriptNameHandle, &scriptNameObj);
Tcl_DictObjGet(nullptr, frameDict, lineNumberHandle, &lineNumberObj);
// Now we have to unbox the information
if (scriptNameObj != nullptr) {
const char *filename = Tcl_GetString(scriptNameObj);
// Do something with this info; COPY IT if you want to keep past the result reset
}
if (lineNumberObj != nullptr) {
int lineNumber = -1;
Tcl_GetIntFromObj(nullptr, lineNumberObj, &lineNumber);
// Do something with this info
}
// Release the result memory, i.e., the dictionary and its contents
Tcl_ResetResult(interp);
Note that neither the file
nor the line
keys are guaranteed to be present; the line
key is usually there, but the file
key is only there when running code that can be tracked back to a file, i.e., back to Tcl_EvalFile()
and related.
Upvotes: 1