从Tcl_HashTable检索对象以销毁对象的问题

时间:2018-12-24 09:06:21

标签: c api tcl

我正在尝试使用Tcl C api创建我的C元素的哈希表,并将它们链接到某个字符串(键是字符串,值是指向我的C对象的指针)。
我的问题是,当我想为我的对象创建destroy函数时,此destroy函数将获取clientData,它是可以转换为我的对象类型的指针,但我无法使用此指针在哈希表中找到该对象(因为键是字符串)。
我该如何解决这个问题? Tcl_linkvar在这种情况下会有用吗?

我将提供一些我编写的代码:

Tcl_InitHashTable(hash_table,TCL_STRING_KEYS);
...
int addMyObj(My_Obj * _obj , const char* _obj_name) {

    Tcl_HashEntry * _new_entry;
    int newptr;
    if (_obj == NULL || strlen(_obj_name) == 0) return TCL_ERROR;
    char * _name = (char *) malloc (strlen(_obj_name));
    if (_name == NULL) return TCL_ERROR;
    _new_entry=Tcl_CreateHashEntry(hash_table,_name,&newptr);
    if (newptr == 0) {
        printf("Error: obj with name %s already exists\n",_obj_name);
        return TCL_ERROR;
    }
    Tcl_SetHashValue(_new_entry,_obj);
    return TCL_OK;
}

void removeMyObj(const char * _obj_name) {
    Tcl_HashEntry * _entry;
    _entry = Tcl_FindHashEntry(hash_table,_obj_name);
    // entry was found
    if (_entry != NULL) {
        My_Obj * _my_obj = (My_Obj * ) Tcl_GetHashValue(_entry);
        Tcl_DeleteHashEntry(_entry);
        delete _my_obj;
    }
    return;
}

My_Obj * getMyObj(const char * _obj_name) {
    Tcl_HashEntry * _entry;
    _entry = Tcl_FindHashEntry(hash_table,_obj_name);
    // entry was found
    if (_entry != NULL) {
        My_Obj * _my_obj = (My_Obj * ) Tcl_GetHashValue(_entry);
        return _my_obj;
    }
    return NULL;
}

// The problem is that in this function I should remove the object from hash table and delete it afterwards.


extern "C" void My_Obj_destroy(ClientData clientData) {

    if (clientData != NULL) {
        My_Obj * _my_obj = (My_Obj *) clientData;
        removeMyObj(_my_obj); // should be removed from the hash table but it is receiving pointer to my_obj and not it's name
        delete _my_obj ;
        _my_obj = NULL;
    }
    return;
}

谢谢

1 个答案:

答案 0 :(得分:1)

有两种处理方法:

  1. 在对象中保留对象名称的副本。
  2. 保留指向在哈希表中为对象命名时创建的Tcl_HashEntry的指针。 (这只是一个指针,但是从创建到删除之前,它一直是有效的。)

对于您而言,最好保留Tcl_HashEntry *(它是Tcl_CreateHashEntry()返回的值或用Tcl_FindHashEntry()查找的值),以便您轻松删除。唯一棘手的一点是,这意味着您必须确保对删除顺序保持谨慎,这意味着在尝试删除整个哈希表时要格外小心。