0

In tcl, we can set the returned characters of a inlined command into a tcl variable as below.

Tcl> set x [pwd]
/home/user_leo/tmp
Tcl> puts $x
/home/user_leo/tmp

We implement a user defined command "get_failed" by Tcl C/C++ API, and this command will print result to screen as below:

Tcl> get_failed
a1 a3 a5 a7

We want we can store the prove result into a tcl variable. But we tried, it failed.

Tcl> set y [get_failed]
a1 a3 a5 a7
Tcl> puts $y

Nothing was stored in variable $y.

So how can I make it work? How can I store the result of user defined tcl command "get_failed" into a tcl variable? I hope it can work as below:

Tcl> set y [get_failed]
a1 a3 a5 a7
Tcl> puts $y
a1 a3 a5 a7

I hope this because I want to pass the result of "get_failed" to another user defined command, sample as below.

Tcl> check_by_method2 [get_failed]
checking a1...
done, pass.
checking a3...
done, fail.
checking a5...
done, pass
checking a7...
done, pass
Leo
  • 59
  • 5
  • 1
    Show a [mcve] for your prove command? Without that, I can only guess that it's printing stuff out instead of using a result. See https://www.tcl.tk/man/tcl8.6/TclLib/SetResult.htm for details. – Shawn Nov 22 '20 at 08:20
  • Yes, I want to use the result of the user define command later. – Leo Nov 22 '20 at 08:26
  • `set y [get_failed]` is correct. The error is almost certainly `get_failed` printing them to stdout (or stderr) instead of returning them. – Andreas Nov 22 '20 at 09:17
  • See https://stackoverflow.com/q/64547745/301832 and https://stackoverflow.com/a/14538125/301832 and https://stackoverflow.com/q/40425550/301832 – Donal Fellows Nov 22 '20 at 14:46

1 Answers1

0

Tcl commands implemented in C return values back to the tcl runtime using Tcl_SetObjResult() or Tcl_SetResult() (For simple strings). As far as we can tell since you haven't provided any example source for your get_failed command, you're printing out values to standard output instead of building up a result object. Since it appears you're wanting to return a list, it might look something like

Tcl_Obj *my_list = Tcl_NewListObj(0, NULL);
// Populate the list however is appropriate for your command
Tcl_ListObjAppendElement(interp, my_list, Tcl_NewStringObj("a1", -1));
Tcl_SetObjResult(interp, my_list);
return TCL_OK;
Shawn
  • 47,241
  • 3
  • 26
  • 60
  • If they're using the Tcl channel I/O, it can be intercepted with a channel “transform”. If they're just printing directly, it's really difficult to intercept (bordering on impossible, depending on what weirdness they're doing in accessing the OS). – Donal Fellows Nov 22 '20 at 14:43
  • @DonalFellows A transchan seems like an awfully complicated approach compared to just returning values. Though I suppose it depends on what the underlying code is doing and how much of it OP controls. – Shawn Nov 22 '20 at 16:29
  • Yes, it works! Thanks a lot! "interp" should be the first parameter of below funtion. Tcl_ListObjAppendElement(interp, my_list, Tcl_NewStringObj("a1", -1)); – Leo Nov 24 '20 at 07:23