Here's my code which shows how to (in short) do a deep copy of a Tcl_Obj structure from C. It stores any unknown type as string and the following in internal represenatation: *list (including sublists) *int/long/double Here's the main code: *deepcopy.c #include #include #include /* external API */ void *Dc_GetTclObj(Tcl_Obj *obj) /* {{{ */ { void *rc; char *otype=""; if (obj->typePtr!=NULL) { otype=obj->typePtr->name; } if (!strcmp(otype,"int")) rc=int_GetTclObj(obj); else if (!strcmp(otype,"long")) rc=long_GetTclObj(obj); else if (!strcmp(otype,"double")) rc=double_GetTclObj(obj); else if (!strcmp(otype,"list")) rc=list_GetTclObj(obj); else rc=str_GetTclObj(obj); return(rc); } /* }}} */ Tcl_Obj *Dc_NewTclObj(void *ptr) /* {{{ */ { struct dcObjHead *oh=ptr; Tcl_Obj *rc=NULL; switch (oh->type) { case DCO_STRING: rc=str_NewTclObj(ptr); break; case DCO_LIST: rc=list_NewTclObj(ptr); break; case DCO_INTEGER: rc=int_NewTclObj(ptr); break; case DCO_DOUBLE: rc=double_NewTclObj(ptr); break; case DCO_LONG: rc=long_NewTclObj(ptr); break; } return(rc); } /* }}} */ void Dc_FreeDcObj(void *ptr) /* {{{ */ { struct dcObjHead *oh=ptr; switch (oh->type) { case DCO_STRING: str_Free(ptr); break; case DCO_LIST: list_Free(ptr); break; case DCO_INTEGER: int_Free(ptr); break; case DCO_LONG: long_Free(ptr); break; case DCO_DOUBLE: double_Free(ptr); break; } } /* }}} */ unsigned long Dc_ObjSize(void *ptr) /* {{{ */ { struct dcObjHead *oh=ptr; return(oh->size); } /* }}} */ /* internal type representations */ static struct dcObjHead *str_GetTclObj(Tcl_Obj *to) /* {{{ */ { struct dcStrObj *rc; unsigned long size; int strlen; char *str; str=Tcl_GetStringFromObj(to,&strlen); size=strlen+1+sizeof(struct dcObjHead); if (rc=(struct dcStrObj *) dc_Malloc(size)) { memcpy(rc->string,str,strlen); rc->string[strlen]='\0'; rc->head.type=DCO_STRING; rc->head.size=size; } return ((struct dcObjHead *) rc); } /* }}} */ Tcl_Obj *str_NewTclObj(struct dcObjHead *o) /* {{{ */ { struct dcStrObj *so=(struct dcStrObj *) o; Tcl_Obj *rc=NULL; if (o->type==DCO_STRING) { rc=Tcl_NewStringObj(so->string,o->size-sizeof(struct dcObjHead)-1); } return(rc); } /* }}} */ static void str_Free(struct dcObjHead *o) /* {{{ */ { if (o->type==DCO_STRING) { dc_Free(o); } } /* }}} */ static struct dcObjHead *int_GetTclObj(Tcl_Obj *to) /* {{{ */ { struct dcIntObj *rc; if (rc=(struct dcIntObj *) dc_Malloc(sizeof(struct dcIntObj))) { Tcl_GetIntFromObj(NULL,to,&rc->value); rc->head.type=DCO_INTEGER; rc->head.size=sizeof(struct dcIntObj); } return ((struct dcObjHead *) rc); } /* }}} */ Tcl_Obj *int_NewTclObj(struct dcObjHead *o) /* {{{ */ { struct dcIntObj *so=(struct dcIntObj *) o; Tcl_Obj *rc=NULL; if (o->type==DCO_INTEGER) { rc=Tcl_NewIntObj(so->value); } return(rc); } /* }}} */ static void int_Free(struct dcObjHead *o) /* {{{ */ { if (o->type==DCO_INTEGER) { dc_Free((void *) o); } } /* }}} */ static struct dcObjHead *long_GetTclObj(Tcl_Obj *to) /* {{{ */ { struct dcLongObj *rc; if (rc=(struct dcLongObj *) dc_Malloc(sizeof(struct dcLongObj))) { Tcl_GetLongFromObj(NULL,to,&rc->value); rc->head.type=DCO_LONG; rc->head.size=sizeof(struct dcLongObj); } return ((struct dcObjHead *) rc); } /* }}} */ Tcl_Obj *long_NewTclObj(struct dcObjHead *o) /* {{{ */ { struct dcLongObj *so=(struct dcLongObj *) o; Tcl_Obj *rc=NULL; if (o->type==DCO_LONG) { rc=Tcl_NewLongObj(so->value); } return(rc); } /* }}} */ static void long_Free(struct dcObjHead *o) /* {{{ */ { if (o->type==DCO_LONG) { dc_Free((void *) o); } } /* }}} */ static struct dcObjHead *double_GetTclObj(Tcl_Obj *to) /* {{{ */ { struct dcDoubleObj *rc; if (rc=(struct dcDoubleObj *) dc_Malloc(sizeof(struct dcDoubleObj))) { Tcl_GetDoubleFromObj(NULL,to,&rc->value); rc->head.type=DCO_DOUBLE; rc->head.size=sizeof(struct dcDoubleObj); } return ((struct dcObjHead *) rc); } /* }}} */ Tcl_Obj *double_NewTclObj(struct dcObjHead *o) /* {{{ */ { struct dcDoubleObj *so=(struct dcDoubleObj *) o; Tcl_Obj *rc=NULL; if (o->type==DCO_DOUBLE) { rc=Tcl_NewDoubleObj(so->value); } return(rc); } /* }}} */ static void double_Free(struct dcObjHead *o) /* {{{ */ { if (o->type==DCO_DOUBLE) { dc_Free((void *) o); } } /* }}} */ static struct dcObjHead *list_GetTclObj(Tcl_Obj *to) /* {{{ */ { Tcl_Obj *elem; struct dcListObj *rc; int size,llen,i; if (Tcl_ListObjLength(NULL,to,&llen)!=TCL_OK) return(NULL); size=sizeof(struct dcListObj)+(llen-1)*sizeof(struct dcListObj *); if (rc=(struct dcListObj *) dc_Malloc(size)) { rc->head.type=DCO_LIST; rc->nelem=llen; for (i=0;ilist[i]=NULL; else { rc->list[i]=Dc_GetTclObj(elem); size+=rc->list[i]->size; } } rc->head.size=size; } return ((struct dcObjHead *) rc); } /* }}} */ Tcl_Obj *list_NewTclObj(struct dcObjHead *o) /* {{{ */ { struct dcListObj *so=(struct dcListObj *) o; Tcl_Obj *rc=NULL,**tbl; int llen,i; if (o->type==DCO_LIST) { llen=so->nelem; if ((tbl=dc_Malloc(llen*sizeof(Tcl_Obj *)))!=NULL) { for (i=0;ilist[i]); } rc=Tcl_NewListObj(llen,tbl); dc_Free(tbl); } } return(rc); } /* }}} */ static void list_Free(struct dcObjHead *o) /* {{{ */ { struct dcListObj *so=o; int i; if (o->type==DCO_LIST) { for (i=0;inelem;i++) { Dc_FreeDcObj(so->list[i]); } dc_Free((void *) o); } } /* }}} */