【问题标题】:Tcl convertion to double not working with large examplesTcl 转换为 double 不适用于大型示例
【发布时间】:2021-10-04 19:35:20
【问题描述】:

我有一个字典列表,我想检索这些字典的一些值。代码如下:

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使用的好例子,我用对了吗?

【问题讨论】:

    标签: c++ tcl c-api


    【解决方案1】:

    你应该(嗯,必须真的)测试Tcl_DictObjGet的结果,看看它是TCL_OK还是TCL_ERROR。它是一个 C API,所以它返回结果代码而不是抛出 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 返回TCL_ERROR 时抛出异常。)

    Tcl_GetDoubleFromObj类似;它使用相同的模式(但通过其成功的 out 参数生成 double,而不是 Tcl_Obj*)。

    如果 dict 持有引用,您不需要 增加值的引用计数,但这应该没问题;绝对合法做你在那里做过的事情(并且取决于你用它做什么,这可能是必要的;细节很重要)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-26
      • 2021-11-14
      • 2014-01-09
      • 2022-10-20
      • 1970-01-01
      • 1970-01-01
      • 2012-05-09
      • 1970-01-01
      相关资源
      最近更新 更多