c++ - C++/Tcl 调用 Tcl_CreateCommand 记录的函数时,我可以检索 Tcl 文件行号吗
问题描述
我使用Tcl_EvalFile
. 我定义了一些自定义命令(使用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 非常可怕,以至于它从未被公开过。)这意味着你需要做这样的事情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);
请注意,既不能保证file
也不能line
保证键存在;line
密钥通常在那里,但只有file
在运行可以追溯到文件的代码时才存在密钥,即回溯Tcl_EvalFile()
和相关。
推荐阅读
- c - 如何将字体设置为用户使用字体选择器选择的字体?
- php - 删除获取请求的 url .php 扩展名和参数?
- vue.js - Vue js如何使用props值到v-model
- nginx - 使用 nginx 反向代理丢失 POST 请求正文
- arrays - 如何将 json 数据显示到 laravel 刀片中?
- php - php sqlsrv 通过多台服务器连接到一个特定的数据库
- java - 如何通过 LLRP 从 EPC RFID 标签读取用户数据(内存)?
- typescript - 如何修复 no-unsafe-any 规则?
- ios - 如何在 Swift 中使用查询语句检索数据?
- elasticsearch - ElasticSearch 词袋字段匹配