从Tcl_哈希表中检索销毁对象时出现问题

从Tcl_哈希表中检索销毁对象时出现问题,c,api,tcl,C,Api,Tcl,我正在尝试使用Tcl C api创建我的C元素的哈希表,并将它们链接到某个字符串(键是string,值是指向我的C对象的指针)。 我的问题是,当我想为我的对象创建destroy函数时,这个destroy函数会获取clientData,这是一个可以强制转换到我的对象类型的指针,但是我在哈希表中找不到这个对象(因为键是字符串)。 我如何解决这个问题?Tcl_linkvar在这种情况下有用吗 我将提供我编写的一些代码: Tcl_InitHashTable(hash_table,TCL_STRING_K

我正在尝试使用Tcl C api创建我的C元素的哈希表,并将它们链接到某个字符串(键是string,值是指向我的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;
}

谢谢

有两种方法可以解决这个问题:

  • 在对象中保留对象名称的副本
  • 保留一个指向在哈希表中为对象命名时创建的
    Tcl\u HashEntry
    的指针。(它只是一个指针,但保证从创建到删除都有效。)

  • 在您的情况下,最好保留
    Tcl\u HashEntry*
    ——它是由
    Tcl\u CreateHashEntry()
    返回的值,或者使用
    Tcl\u FindHashEntry()
    进行查找,以便您可以轻松地删除。唯一棘手的一点是,这意味着您必须确保小心删除顺序,这意味着您在试图删除整个哈希表时要小心。

    只需将名称添加到您的objI中即可。我不想这样做,因为这样我需要为我的对象实现一个包装器。我还可以创建一个表,将我的对象指针链接到我给它的名称,但我再次认为有更好的方法用名称和对象创建一个结构,并将其放入哈希表中,以及当哈希表包含此结构时我将如何找到我的对象??键将是字符串/指针?您确定理解指针和结构吗?如果
    s
    是具有
    name
    obj
    的结构,请使用名称进行查找,并使用
    s->obj
    获取您的obj,在销毁时使用
    s->name
    调用remove。实现说明:
    Tcl_CreateHashEntry()
    Tcl_FindHashEntry()
    实际上是同一API函数的宏前端-它们毕竟做的事情几乎相同-但将它们视为单独的。此外,还有一个单独的调用,用于从
    Tcl\u HashEntry返回其键。这是一个便宜的调用,但类型混乱(因为C API的多态性)。