C++/Tcl 我可以在调用 Tcl_CreateCommand 记录的函数时检索 Tcl 文件行号吗

C++/Tcl Can I retrieve Tcl file line number when a function recorded by Tcl_CreateCommand is invoked

我 运行 来自使用 Tcl_EvalFile 的 C++ 程序的 Tcl 脚本。我定义了一些自定义命令(使用 Tcl_CreateCommand),因此当在文件中找到它们时会调用一个回调,然后我可以 运行 一些 C++ 代码(TclInvokeStringCommand 调用给定的回调 Tcl_CreateCommand,回调类型为int (*executeCmd)( ClientData data, Tcl_Interp *interp, int argc, const char *argv[] )).

我想知道被调用的回调函数中的脚本文件名和行号。

我可以使用 ((Interp*) interp)->scriptFile 获取脚本文件名。

但是,我无法获取脚本文件行号。有没有办法检索它(或以任何方式计算它)?

信息仅通过 info frame 命令在 Tcl 级别公开。 (内部 C API 因为它太可怕了,所以它从来没有被制作过 public。)这意味着你需要用 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);

请注意,fileline 键都不能保证存在; line 键通常在那里,但 file 键仅在 运行 代码可以追溯到文件时才存在,即,回到 Tcl_EvalFile() 和相关。