获取在C++中实例化的TCL解释器中执行代码的行号
Getting the line number of executing code in TCL-Interpreter instantiated in C++
我在C++代码中使用CPPTCL实例化TCL解释器的一个实例。然后,我可以根据需要使用"pTclInterpreter->eval(script);"来执行脚本。我还将自己的TCL函数定义为C++函数,并通过"pTclInterpreter->def("getValueCmd",getValueCmd);"使其可在TCL脚本中使用。效果也不错。
现在,对于C++实现的TCL函数中的消息传递(info/error),我需要从调用该函数的脚本行中知道。我找到了这篇文章:获取TCL中执行代码的行号,当我在独立的TCL shell中执行TCL脚本时,我收到了预期的结果:全球的28程序A23程序B18程序C13程序D9
但是,当我在C++实例化的TCL解释器中执行相同的脚本时,我收到的却是:全球的28程序A3.程序B3.程序C3.程序D3
第28行的全局调用正确。但对于函数调用,它总是"3",这似乎指的是被调用函数中的第三行,而不是完整脚本中的行。
这给我留下了两个问题:1.)如何检测TCL脚本行称我的C++函数?2.)如果TCL脚本的行为在这一点上有所不同,我还能在哪里期待差异?
在我愚蠢的C++代码中。
#include <systemc.h>
#include "cpptcl.h"
sc_event go;
Tcl::interpreter *pTclInterpreter;
int MOD(std::string module, std::string cmd, int param1, int param2){
/*
Function to simulate the execution of an IFS command.
*/
/*
Here we would have the code that creates the proper cmdObj
*/
std::cout << sc_time_stamp() << ": creatingCmdObj(";
std::cout << module;
std::cout << ", " << cmd;
std::cout << ", " << param1;
std::cout << ", " << param2;
std::cout << ")" << std::endl;
// pTclInterpreter->eval("puts [ dict get [info frame [info frame -1] ] line ]");
return 0;
}
int getValueCmd(){
/*
Function to simulate the execution of a getValue
*/
std::cout << sc_time_stamp() << ": executing getValueCmd." << std::endl;
std::cout << sc_time_stamp() << ": TCL waiting for all TBMs to catch up." << std::endl;
wait(go);
std::cout << sc_time_stamp() << ": TBMs in sync. TCL interpreter to continue." << std::endl;
return 0;
}
int read_trace(const int& v, void *) {
cout << "read trace triggered: wait(10, SC_NS)" << endl;
wait(10, SC_NS);
return v;
}
SC_MODULE (wait_example) {
void tclInterpreter() {
std::cout << sc_time_stamp() << ": Starting TCL interpreter!" << std::endl;
// new TCL
pTclInterpreter = new(Tcl::interpreter);
// register the C++ function to be called from TCL
pTclInterpreter->def("MOD", MOD);
pTclInterpreter->def("getValueCmd", getValueCmd);
// register read trace for variable
pTclInterpreter->def_read_trace("tracedVar", "read", read_trace);
// load the script
// ifstream script("helloworld.tcl");
ifstream script("test.tcl");
// run the script with the given arguments
pTclInterpreter->eval(script);
cout << sc_time_stamp() << ": Terminating Simulation." << std::endl;
sc_stop(); // sc_stop triggers end of simulation
}
void ifscontroller() {
wait(100, SC_NS);
go.notify();
}
SC_CTOR(wait_example) {
SC_THREAD(tclInterpreter);
SC_THREAD(ifscontroller);
}
};
int sc_main (int argc, char* argv[]) {
wait_example object("wait");
sc_start(0, SC_NS); // First time called will init schedular
sc_start(); // Run the simulation till sc_stop is encountered
return 0;// Terminate simulation
}
这也使用了SystemC,我认为它在这里不再重要。如您所见,我创建了一个TCL解释器实例,并让指针pTclInterpreter引用它。然后我使用"pTclInterpreter->eval(script);"从引用中执行脚本。但结果不同于在纯壳中这样做。
您的过程是通过source
创建文件的吗?(好吧,使用Tcl_EvalFile
及其关系也可以。)如果没有,它们就不会有全局行号,因为此时没有合适的上下文可用。实际工作的方式实际上很棘手,因此使用source
(或其调用的C API)是迄今为止最简单的工作方法。
更改以上行
pTclInterpreter->eval(script);
至
pTclInterpreter->eval("source test.tcl");
更新:我根据需要完成了演示。我现在可以创建一个TCL解释器,并定义可从TCL脚本调用的C++函数。这些TCL-调用的C++函数现在可以访问TCL解释器实例,以确定哪个命名文件中的哪行脚本调用了它们。代码:
#include <systemc.h>
#include "cpptcl.h"
sc_event go;
Tcl::interpreter *pTclInterpreter;
int MOD(std::string module, std::string cmd, int param1, int param2){
/*
Here we would have the code that creates the proper cmdObj and adds it to
the IFS controller's list of cmdObj. From there the TBMs will receive it
during their executeNextCommand loop.
*/
pTclInterpreter->eval("set IFS_scriptLine [dict get [info frame [expr [info frame] -1] ] line]");
pTclInterpreter->eval("set IFS_scriptName [dict get [info frame [expr [info frame] -1] ] file]");
std::cout << sc_time_stamp() << "; " << pTclInterpreter->read_variable<std::string>("IFS_scriptName") << "(";
std::cout << pTclInterpreter->read_variable<int>("IFS_scriptLine") << ")";
std::cout << ": creatingCmdObj(";
std::cout << module;
std::cout << ", " << cmd;
std::cout << ", " << param1;
std::cout << ", " << param2;
std::cout << ")" << std::endl;
return 0;
}
int getValueCmd(){
pTclInterpreter->eval("set IFS_scriptLine [dict get [info frame [expr [info frame] -1] ] line]");
pTclInterpreter->eval("set IFS_scriptName [dict get [info frame [expr [info frame] -1] ] file]");
std::cout << sc_time_stamp() << "; " << pTclInterpreter->read_variable<std::string>("IFS_scriptName") << "(";
std::cout << pTclInterpreter->read_variable<int>("IFS_scriptLine") << ")";
std::cout << ": executing getValueCmd." << std::endl;
std::cout << sc_time_stamp() << ": TCL waiting for all TBMs to catch up." << std::endl;
wait(go);
std::cout << sc_time_stamp() << ": TBMs in sync. TCL interpreter to continue." << std::endl;
return 0;
}
int read_trace(const int& v, void *) {
cout << "read trace triggered: wait(10, SC_NS)" << endl;
wait(10, SC_NS);
return v;
}
SC_MODULE (wait_example) {
void tclInterpreter() {
std::cout << sc_time_stamp() << ": Starting TCL interpreter!" << std::endl;
// new TCL
pTclInterpreter = new(Tcl::interpreter);
// register the C++ function to be called from TCL
pTclInterpreter->def("MOD", MOD);
pTclInterpreter->def("getValueCmd", getValueCmd);
// register read trace for variable
pTclInterpreter->def_read_trace("tracedVar", "read", read_trace);
// run the script with the given arguments
pTclInterpreter->eval("source helloworld.tcl");
cout << sc_time_stamp() << ": Terminating Simulation." << std::endl;
sc_stop(); // sc_stop triggers end of simulation
}
void ifscontroller() {
wait(100, SC_NS);
go.notify();
}
SC_CTOR(wait_example) {
SC_THREAD(tclInterpreter);
SC_THREAD(ifscontroller);
}
};
int sc_main (int argc, char* argv[]) {
wait_example object("wait");
sc_start(0, SC_NS); // First time called will init schedular
sc_start(); // Run the simulation till sc_stop is encountered
return 0;// Terminate simulation
}
执行后的结果:
0 s: Starting TCL interpreter!
SystemC 2.3.0-ASI --- May 16 2014 17:16:28
Copyright (c) 1996-2012 by all Contributors,
ALL RIGHTS RESERVED
"Executing script and creating cmdObj."
0 s; myCppTcl/helloworld.tcl(5): creatingCmdObj(tbm1, userDefined1, 7, 12)
0 s; myCppTcl/helloworld.tcl(6): creatingCmdObj(tbm2, read, 9, 1)
0 s; myCppTcl/helloworld.tcl(8): creatingCmdObj(tbm2, write, 6, 6)
0 s; myCppTcl/helloworld.tcl(9): creatingCmdObj(tbm1, userDefined4, 2, 4)
0 s; myCppTcl/helloworld.tcl(14): executing getValueCmd.
0 s: TCL waiting for all TBMs to catch up.
100 ns: TBMs in sync. TCL interpreter to continue.
100 ns; myCppTcl/helloworld.tcl(19): creatingCmdObj(tbm1, read, 3, 0)
100 ns; myCppTcl/helloworld.tcl(19): creatingCmdObj(tbm1, read, 4, 1)
100 ns; myCppTcl/helloworld.tcl(19): creatingCmdObj(tbm1, read, 5, 2)
100 ns; myCppTcl/helloworld.tcl(19): creatingCmdObj(tbm1, read, 6, 3)
100 ns; myCppTcl/helloworld.tcl(19): creatingCmdObj(tbm1, read, 7, 4)
100 ns; myCppTcl/helloworld.tcl(19): creatingCmdObj(tbm1, read, 8, 5)
read trace triggered: wait(10, SC_NS)
10
read trace triggered: wait(10, SC_NS)
10
read trace triggered: wait(10, SC_NS)
10
read trace triggered: wait(10, SC_NS)
10
read trace triggered: wait(10, SC_NS)
10
read trace triggered: wait(10, SC_NS)
10
160 ns; myCppTcl/testSource.tcl(7): creatingCmdObj(tbm1, userDefined1, 7, 12)
160 ns; myCppTcl/testSource.tcl(4): creatingCmdObj(tbm1, userDefined1, 7, 12)
160 ns: Terminating Simulation.
Info: /OSCI/SystemC: Simulation stopped by user.
使用的TCL脚本:
puts {"Executing script and creating cmdObj."}
# Regular IFS commands to be put here.
# Each command creates individual cmdObj
MOD tbm1 userDefined1 [expr 3+4] [expr 4*3]
MOD tbm2 read [expr 3*3] 1
set myVar 6
MOD tbm2 write [expr 12-6] $myVar
MOD tbm1 userDefined4 [expr 20/10] 4
# Need to receive value from IFS. Cannot
# continue executing script.
# getValueCmd makes us wait for TBMs
getValueCmd
# Regular IFS commands to be put here.
# Each command creates individual cmdObj
for { set i 0 } { $i <= 5 } { incr i } {
MOD tbm1 read [expr 3+$i] $i
}
set tracedVar 10
# Assuming that tracedVar is an IFS-Signal type var, it is required
# to synchronize the IFS and it's testbench modules. For demonstration
# the read call back for the following command will wait 10 ns.
for { set i 0 } { $i <= 5 } { incr i } {
puts $tracedVar
}
# Let us see what file name and line numbers are communicated when we use source
source testSource.tcl
下一个
#!/usr/bin/tclsh
proc testProc {} {
# Execute an IFS command in a procedure to see what file and line info is communicated
MOD tbm1 userDefined1 [expr 3+4] [expr 4*3]
}
MOD tbm1 userDefined1 [expr 3+4] [expr 4*3]
- 需要将此代码更改为执行代码
- 当前不会命中断点。没有调试器目标代码类型的可执行代码与此文件关联
- 单步执行代码时重复上一行
- 如何使用介子在C++中执行代码覆盖?
- Visual Studio 2017,C++,在单步执行代码时指向错误的行
- 在 R 中执行C++代码
- 通过 dll 注入在主线程中执行代码
- 无法在 c++ 中循环后执行代码
- 执行C 代码时快速频繁的文件访问
- 执行 C++ 代码后出错
- 一个人如何从代表函数的字符串中执行运行时执行C 代码
- 是否可以在程序崩溃后执行代码?
- 第一次在 Linux 上执行 c++ 代码的时间非常慢
- 计算 JSON 中的条目数并相应地执行代码
- 将在 CATCH 块之后执行代码
- 分析执行C++代码的每一行所花费的确切时间
- 我在执行代码时不断得到"Bus Error"?
- c while()..执行代码行的条件
- 从并行线程在主 Maya 线程上执行代码
- 在调用GNUPLOT之后,如何继续执行C 代码