Tcl 转换为 double 不适用于大型示例
Tcl convertion to double not working with large examples
我有一个字典列表,我想检索这些字典的一些值。这是代码:
void Get_Dict_Value(Tcl_Interp *interp, Tcl_Obj *dict, const char* key, std::function<void(Tcl_Obj*)> data_handler) {
Tcl_Obj* val_ptr;
Tcl_Obj* key_ptr = Tcl_NewStringObj(key, -1);
Tcl_IncrRefCount(key_ptr);
Tcl_DictObjGet(interp, dict, key_ptr, &val_ptr);
Tcl_IncrRefCount(val_ptr);
data_handler(val_ptr);
Tcl_DecrRefCount(val_ptr);
Tcl_DecrRefCount(key_ptr);
}
void Write_Float_Dict(Tcl_Interp *interp, Tcl_Obj *dict, const char* key) {
Get_Dict_Value(interp, dict, key, [&interp](Tcl_Obj *val_ptr) {
double double_value;
Tcl_GetDoubleFromObj(interp, val_ptr, &double_value); //crashing here
std::cout << "the value: " << double_value << std::endl;
});
}
static int Dict_Test(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
const char* script = R"__(
proc my_ns::bla {} {
set my_list ""
set my_dict [dict create]
dict set my_dict my_key 123789
dict set my_dict my_key_2 456
lappend my_list $my_dict
return $my_list;
}
)__";
Tcl_Eval(interp, script);
Tcl_Eval(interp, "my_ns::bla");
Tcl_Obj* my_list = Tcl_GetObjResult(interp);
Tcl_IncrRefCount(my_list);
Tcl_Obj* my_dict;
Tcl_ListObjIndex(interp, my_list, 0, &my_dict);
Tcl_IncrRefCount(my_dict);
Write_Float_Dict(interp, my_dict, "my_key"); //prints: the value: 123789
Write_Float_Dict(interp, my_dict, "my_key_2"); //prints: the value: 456
Tcl_DecrRefCount(my_dict);
Tcl_DecrRefCount(my_list);
return TCL_OK;
}
如果我只是 运行 示例,这将起作用。但是当我尝试使用一个特定的大示例时,我在第一次 Tcl_GetDoubleFromObj
出现时崩溃了。我是否遗漏了有关引用计数的内容?另外,我没有找到关于 Tcl_DictObjGet
用法的好例子,我用对了吗?
你应该(好吧,必须真的)测试Tcl_DictObjGet
的结果,看看它是TCL_OK
还是TCL_ERROR
。它是 C API,所以它 returns 结果代码而不是抛出 C++ 异常。
void Get_Dict_Value(Tcl_Interp *interp, Tcl_Obj *dict, const char* key, std::function<void(Tcl_Obj*)> data_handler) {
Tcl_Obj* val_ptr = NULL;
Tcl_Obj* key_ptr = Tcl_NewStringObj(key, -1);
Tcl_IncrRefCount(key_ptr);
if (Tcl_DictObjGet(interp, dict, key_ptr, &val_ptr) == TCL_OK) {
Tcl_IncrRefCount(val_ptr);
data_handler(val_ptr);
Tcl_DecrRefCount(val_ptr);
}
Tcl_DecrRefCount(key_ptr);
}
(另一种选择是在 Tcl_DictObjGet
returns TCL_ERROR
时抛出异常。)
与Tcl_GetDoubleFromObj
类似;它使用相同的模式(但在成功时通过其 out 参数生成 double
,而不是 Tcl_Obj*
)。
如果字典持有引用,您不需要增加值的引用计数,但这应该没问题;做你在那里做的事情绝对是 合法的(根据你用它做的事情,这可能是必要的;细节很重要)。
我有一个字典列表,我想检索这些字典的一些值。这是代码:
void Get_Dict_Value(Tcl_Interp *interp, Tcl_Obj *dict, const char* key, std::function<void(Tcl_Obj*)> data_handler) {
Tcl_Obj* val_ptr;
Tcl_Obj* key_ptr = Tcl_NewStringObj(key, -1);
Tcl_IncrRefCount(key_ptr);
Tcl_DictObjGet(interp, dict, key_ptr, &val_ptr);
Tcl_IncrRefCount(val_ptr);
data_handler(val_ptr);
Tcl_DecrRefCount(val_ptr);
Tcl_DecrRefCount(key_ptr);
}
void Write_Float_Dict(Tcl_Interp *interp, Tcl_Obj *dict, const char* key) {
Get_Dict_Value(interp, dict, key, [&interp](Tcl_Obj *val_ptr) {
double double_value;
Tcl_GetDoubleFromObj(interp, val_ptr, &double_value); //crashing here
std::cout << "the value: " << double_value << std::endl;
});
}
static int Dict_Test(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
const char* script = R"__(
proc my_ns::bla {} {
set my_list ""
set my_dict [dict create]
dict set my_dict my_key 123789
dict set my_dict my_key_2 456
lappend my_list $my_dict
return $my_list;
}
)__";
Tcl_Eval(interp, script);
Tcl_Eval(interp, "my_ns::bla");
Tcl_Obj* my_list = Tcl_GetObjResult(interp);
Tcl_IncrRefCount(my_list);
Tcl_Obj* my_dict;
Tcl_ListObjIndex(interp, my_list, 0, &my_dict);
Tcl_IncrRefCount(my_dict);
Write_Float_Dict(interp, my_dict, "my_key"); //prints: the value: 123789
Write_Float_Dict(interp, my_dict, "my_key_2"); //prints: the value: 456
Tcl_DecrRefCount(my_dict);
Tcl_DecrRefCount(my_list);
return TCL_OK;
}
如果我只是 运行 示例,这将起作用。但是当我尝试使用一个特定的大示例时,我在第一次 Tcl_GetDoubleFromObj
出现时崩溃了。我是否遗漏了有关引用计数的内容?另外,我没有找到关于 Tcl_DictObjGet
用法的好例子,我用对了吗?
你应该(好吧,必须真的)测试Tcl_DictObjGet
的结果,看看它是TCL_OK
还是TCL_ERROR
。它是 C API,所以它 returns 结果代码而不是抛出 C++ 异常。
void Get_Dict_Value(Tcl_Interp *interp, Tcl_Obj *dict, const char* key, std::function<void(Tcl_Obj*)> data_handler) {
Tcl_Obj* val_ptr = NULL;
Tcl_Obj* key_ptr = Tcl_NewStringObj(key, -1);
Tcl_IncrRefCount(key_ptr);
if (Tcl_DictObjGet(interp, dict, key_ptr, &val_ptr) == TCL_OK) {
Tcl_IncrRefCount(val_ptr);
data_handler(val_ptr);
Tcl_DecrRefCount(val_ptr);
}
Tcl_DecrRefCount(key_ptr);
}
(另一种选择是在 Tcl_DictObjGet
returns TCL_ERROR
时抛出异常。)
与Tcl_GetDoubleFromObj
类似;它使用相同的模式(但在成功时通过其 out 参数生成 double
,而不是 Tcl_Obj*
)。
如果字典持有引用,您不需要增加值的引用计数,但这应该没问题;做你在那里做的事情绝对是 合法的(根据你用它做的事情,这可能是必要的;细节很重要)。