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.h]] #ifndef DEEPCOPY_H #define DEEPCOPY_H 1 #include void *Dc_GetTclObj(Tcl_Obj *obj); Tcl_Obj *Dc_NewTclObj(void *ptr); void Dc_FreeDcObj(void *ptr); unsigned long Dc_ObjSize(void *ptr); #endif [[deepcopyInt.h]] #ifndef DEEPCOPYINT_H #define DEEPCOPYINT_H 1 #define DCO_STRING 1 #define DCO_INTEGER 2 #define DCO_LONG 3 #define DCO_DOUBLE 4 #define DCO_LIST 5 #ifdef AOLSERVER #define dc_Malloc Ns_Alloc #define dc_Free Ns_Free #else #define dc_Malloc Tcl_Alloc #define dc_Free Tcl_Free #endif /* objhead */ struct dcObjHead { short type; unsigned long size; // including dcObjHead }; /* int object */ struct dcIntObj { struct dcObjHead head; int value; }; static struct dcObjHead *int_GetTclObj(Tcl_Obj *to); Tcl_Obj *int_NewTclObj(struct dcObjHead *o); static void int_Free(struct dcObjHead *o); /* long object */ struct dcLongObj { struct dcObjHead head; long value; }; static struct dcObjHead *long_GetTclObj(Tcl_Obj *to); Tcl_Obj *long_NewTclObj(struct dcObjHead *o); static void long_Free(struct dcObjHead *o); /* double object */ struct dcDoubleObj { struct dcObjHead head; double value; }; static struct dcObjHead *double_GetTclObj(Tcl_Obj *to); Tcl_Obj *double_NewTclObj(struct dcObjHead *o); static void double_Free(struct dcObjHead *o); /* string object */ struct dcStrObj { struct dcObjHead head; char string[1]; }; static struct dcObjHead *str_GetTclObj(Tcl_Obj *to); Tcl_Obj *str_NewTclObj(struct dcObjHead *o); static void str_Free(struct dcObjHead *o); /* list object */ struct dcListObj { struct dcObjHead head; int nelem; struct dcObjHead *list[1]; }; static struct dcObjHead *list_GetTclObj(Tcl_Obj *to); Tcl_Obj *list_NewTclObj(struct dcObjHead *o); static void list_Free(struct dcObjHead *o); #endif [[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); } }