// Works exactly as Eval with exception that it writes the result of executed // code into `out`. func (ir *Interpreter) EvalAs(out interface{}, format string, args ...interface{}) error { // interpreter thread if C.Tcl_GetCurrentThread() == ir.ir.thread { ir.ir.cmdbuf.Reset() err := sprintf(&ir.ir.cmdbuf, format, args...) if err != nil { return ir.ir.filt(err) } err = ir.ir.eval_as(out, ir.ir.cmdbuf.Bytes()) return ir.ir.filt(err) } // foreign thread buf := buffer_pool.get() err := sprintf(&buf, format, args...) if err != nil { buffer_pool.put(buf) return ir.ir.filt(err) } script := buf.Bytes() err = ir.ir.run_and_wait(func() error { return ir.ir.filt(ir.ir.eval_as(out, script)) }) buffer_pool.put(buf) return err }
// Unregisters (deletes) previously registered command set within the `name` // namespace. func (ir *Interpreter) UnregisterCommands(name string) error { if C.Tcl_GetCurrentThread() == ir.ir.thread { return ir.ir.filt(ir.ir.unregister_commands(name)) } return ir.ir.run_and_wait(func() error { return ir.ir.filt(ir.ir.unregister_commands(name)) }) }
// Register multiple TCL command within the `name` namespace. The method uses // runtime reflection and registers only those methods of the `val` which have // one of the following prefixes: "TCL" or "TCL_". The name of the resulting // command doesn't include the prefix. func (ir *Interpreter) RegisterCommands(name string, val interface{}) error { if C.Tcl_GetCurrentThread() == ir.ir.thread { return ir.ir.filt(ir.ir.register_commands(name, val)) } return ir.ir.run_and_wait(func() error { return ir.ir.filt(ir.ir.register_commands(name, val)) }) }
func (ir *Interpreter) UploadImage(name string, img image.Image) error { if C.Tcl_GetCurrentThread() == ir.ir.thread { return ir.ir.filt(ir.ir.upload_image(name, img)) } return ir.ir.run_and_wait(func() error { return ir.ir.filt(ir.ir.upload_image(name, img)) }) }
// Works the same way as Eval("%{}", byte_slice), but avoids unnecessary // buffering. func (ir *Interpreter) EvalBytes(s []byte) error { if C.Tcl_GetCurrentThread() == ir.ir.thread { return ir.ir.filt(ir.ir.eval(s)) } return ir.ir.run_and_wait(func() error { return ir.ir.filt(ir.ir.eval(s)) }) }
func (ir *Interpreter) Eval(args ...interface{}) error { if C.Tcl_GetCurrentThread() == ir.ir.thread { return ir.ir.filt(ir.ir.eval(args...)) } return ir.ir.run_and_wait(func() error { return ir.ir.filt(ir.ir.eval(args...)) }) }
// Every TCL error goes through the filter passed to this function. If you pass // nil, then no error filter is set. func (ir *Interpreter) ErrorFilter(filt func(error) error) { if C.Tcl_GetCurrentThread() == ir.ir.thread { ir.ir.errfilt = filt } ir.ir.run_and_wait(func() error { ir.ir.errfilt = filt return nil }) }
func new_interpreter(init interface{}) (*interpreter, error) { ir := &interpreter{ C: C.Tcl_CreateInterp(), errfilt: func(err error) error { return err }, commands: make(map[string]interface{}), methods: make(map[string]interface{}), method_handles: make(map[string][]int), valuesbuf: make([]reflect.Value, 0, 10), queue: make(chan async_action, 50), thread: C.Tcl_GetCurrentThread(), } C.Tcl_FindExecutable(C.CString(os.Args[0])) switch realinit := init.(type) { case string: err := ir.eval([]byte(realinit)) if err != nil { panic(err) } case func(*interpreter): realinit(ir) } status := C.Tcl_Init(ir.C) if status != C.TCL_OK { return nil, errors.New(C.GoString(C.Tcl_GetStringResult(ir.C))) } status = C.Tk_Init(ir.C) if status != C.TCL_OK { return nil, errors.New(C.GoString(C.Tcl_GetStringResult(ir.C))) } ir.id = global_handles.get_handle_for_value(ir) runtime.SetFinalizer(ir, release_interpreter) return ir, nil }
func new_interpreter() (*interpreter, error) { ir := &interpreter{ C: C.Tcl_CreateInterp(), errfilt: func(err error) error { return err }, commands: make(map[string]interface{}), channels: make(map[string]interface{}), valuesbuf: make([]reflect.Value, 0, 10), queue: make(chan async_action, 50), thread: C.Tcl_GetCurrentThread(), } status := C.Tcl_Init(ir.C) if status != C.TCL_OK { return nil, errors.New(C.GoString(C.Tcl_GetStringResult(ir.C))) } status = C.Tk_Init(ir.C) if status != C.TCL_OK { return nil, errors.New(C.GoString(C.Tcl_GetStringResult(ir.C))) } return ir, nil }
func (ir *Interpreter) MainLoop() { ir.thread = C.Tcl_GetCurrentThread() C.Tk_MainLoop() }