Index: tcc4tcl.c ================================================================== --- tcc4tcl.c +++ tcc4tcl.c @@ -30,11 +30,11 @@ static void Tcc4tclErrorFunc(Tcl_Interp * interp, char * msg) { Tcl_AppendResult(interp, msg, "\n", NULL); } -static void Tcc4tclCCommandDeleteProc (ClientData cdata) { +static void Tcc4tclCCommandDeleteProc(ClientData cdata) { struct TclTCCState *ts; TCCState *s ; ts = (struct TclTCCState *) cdata; s = ts->s; @@ -41,10 +41,22 @@ ts->s = NULL; ckfree((void *) ts); } + +static void Tcc4tclDeleteClientData(ClientData cdata) { + /* + * ClientData is a Tcl_Obj*, that was passed in + * at command creation + */ + Tcl_Obj *cdata_o = (Tcl_Obj *)cdata; + + if (cdata_o != NULL) { + Tcl_DecrRefCount(cdata_o); + } +} static int Tcc4tclHandleCmd ( ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]){ Tcl_WideInt val; Tcl_Obj *val_o; void *val_p; @@ -134,14 +146,15 @@ val_p = (void *) val; tcc_add_symbol(s,Tcl_GetString(objv[2]), val_p); return TCL_OK; case TCC4TCL_COMMAND: - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "tclname cname"); + if (objc != 4 && objc != 5) { + Tcl_WrongNumArgs(interp, 2, objv, "tclname cname ?clientData?"); return TCL_ERROR; } + if (!ts->relocated) { if(tcc_relocate(s, TCC_RELOCATE_AUTO)!=0) { Tcl_AppendResult(interp, "relocating failed", NULL); return TCL_ERROR; } else { @@ -152,13 +165,21 @@ val_p = tcc_get_symbol(s, Tcl_GetString(objv[3])); if (val_p == NULL) { Tcl_AppendResult(interp, "symbol '", Tcl_GetString(objv[3]),"' not found", NULL); return TCL_ERROR; } + + /* the ClientData */ + if (objc == 5) { + val_o = objv[4]; + Tcl_IncrRefCount(val_o); + } else { + val_o = NULL; + } /*printf("symbol: %x\n",val); */ - Tcl_CreateObjCommand(interp,Tcl_GetString(objv[2]),val_p,NULL,NULL); + Tcl_CreateObjCommand(interp, Tcl_GetString(objv[2]), val_p, val_o, Tcc4tclDeleteClientData); return TCL_OK; case TCC4TCL_COMPILE: if(ts->relocated == 1) { Tcl_AppendResult(interp, "code already relocated, cannot compile more",NULL); return TCL_ERROR; Index: tcc4tcl.tcl ================================================================== --- tcc4tcl.tcl +++ tcc4tcl.tcl @@ -55,14 +55,18 @@ }] return $handle } - proc _linktclcommand {handle cSymbol tclCommand} { + proc _linktclcommand {handle cSymbol args} { upvar #0 $handle state + set argc [llength $args] + if {$argc != 1 && $argc != 2} { + return -code error "_linktclcommand handle cSymbol tclCommand ?clientData?" + } - lappend state(procs) $cSymbol $tclCommand + lappend state(procs) $cSymbol $args } proc _add_include_path {handle args} { upvar #0 $handle state @@ -91,11 +95,11 @@ set tclname [lindex $wrap 2] append state(code) $wrapped "\n" append state(code) $wrapper "\n" - lappend state(procs) $name $tclname + lappend state(procs) $name [list $tclname] } proc _cproc {handle name adefs rtype {body "#"}} { upvar #0 $handle state @@ -106,11 +110,11 @@ set tclname [lindex $wrap 2] append state(code) $wrapped "\n" append state(code) $wrapper "\n" - lappend state(procs) $name $tclname + lappend state(procs) $name [list $tclname] } proc _ccode {handle code} { upvar #0 $handle state @@ -404,21 +408,35 @@ switch -- $state(type) { "memory" { # No additional code needed if {$outputOnly} { if {[info exists state(procs)] && [llength $state(procs)] > 0} { - foreach {procname cname} $state(procs) { - append code "/* Immediate: Tcl_CreateObjCommand(interp, \"$procname\", $cname, NULL, NULL); */\n" + foreach {procname cname_obj} $state(procs) { + set cname [lindex $cname_obj 0] + + if {[llength $cname_obj] > 1} { + set obj [lindex $cname_obj 1] + } else { + set obj "NULL" + } + + append code "/* Immediate: Tcl_CreateObjCommand(interp, \"$procname\", $cname, $obj, Tcc4tclDeleteClientData); */\n" } } } } "exe" - "dll" { if {[info exists state(procs)] && [llength $state(procs)] > 0} { append code "int _initProcs(Tcl_Interp *interp) \{\n" - foreach {procname cname} $state(procs) { + foreach {procname cname_obj} $state(procs) { + set cname [lindex $cname_obj 0] + + if {[llength $cname_obj] != 1} { + error "ClientData not supported in exe / dll mode" + } + append code " Tcl_CreateObjCommand(interp, \"$procname\", $cname, NULL, NULL);\n" } append code "\}" } @@ -436,11 +454,17 @@ append code " return TCL_ERROR;\n" append code " \}\n" append code "#endif\n" if {[info exists state(procs)] && [llength $state(procs)] > 0} { - foreach {procname cname} $state(procs) { + foreach {procname cname_obj} $state(procs) { + set cname [lindex $cname_obj 0] + + if {[llength $cname_obj] != 1} { + error "ClientData not supported in exe / dll mode" + } + append code " Tcl_CreateObjCommand(interp, \"$procname\", $cname, NULL, NULL);\n" } } append code " Tcl_PkgProvide(interp, \"$packageName\", \"$packageVersion\");\n" @@ -484,12 +508,12 @@ switch -- $state(type) { "memory" { tcc compile $code if {[info exists state(procs)] && [llength $state(procs)] > 0} { - foreach {procname cname} $state(procs) { - tcc command $procname $cname + foreach {procname cname_obj} $state(procs) { + tcc command $procname {*}$cname_obj } } } "package" - "dll" - "exe" {