Dear Ivan and Roderick,
James Wettenhall used to maintain a nice set of R Tcl/Tk examples, but I
can't find them now. If anyone has copies of Wettenhall's web pages,
I'd
be happy to try to get permission to re-post them in an accessible place
-- I'm cc'ing James at the old address I have for him.
In addition, Roderick, you might want to take a look at Philippe
Grosjean's tcltk2 package on CRAN, which adds capabilities to the tcltk
package. I'm also cc'ing Philippe, who might have a copy of
Wettenhall's
examples.
Best,
John
On 2022-03-16 7:19 a.m., Ivan Krylov wrote:> ? Tue, 15 Mar 2022 19:27:13 +0000 (UTC)
> Roderick <hruodr at gmail.com> ?????:
>
>>> library(tcltk)
>>> .Tcl("set k 2")
>> <Tcl> 2
>>
>> How do I access the variable k from R?
>
> tclvalue('k') can give you the string representation of the
variable.
> With R-controlled variables (the tclVar interface), you can use tclObj
> to get other representations of variables and avoid quoting hell. You
> can also get the Tcl object using tcl('set', 'k').
>
>> And how do I access R variables from tcl?
>
> I think that you have to use callbacks for that. At least I see no way
> of giving R environments to Tcl, and that would be the basis of
> accessing arbitrary variables.
>
>> Since ::RTcl2 existed, b<-tclVar() should have created something
>> different and new, perhaps ::RTcl3.
>
> The idea behind the tclVar interface was to avoid dealing with names
> (since creating global variables manually may result in namespace
> collisions) and only use tclvalue() and friends to access the
> variables.
>
>> Can I at least be sure that all variables generated by tclVar()
>> and tclArray() are of the form ::RTcl2N ?
>
> Yes, this has been mentioned in the R News articles (see below) and you
> can see that in the tclVar/tclArray implementations. If you peek behind
> the curtain, you'll see that R assumes that the number of global Tcl
> variables stored in .TkRoot$env$TclVarCount is correct.
>
>> And what are these callbacks, are they functions callable from Tcl?
>> The following does not work:
>>
>>> f<-function() return(7)
>>> f()
>> [1] 7
>>> .Tcl.args(f)
>> [1] " { R_call 0x80e29e2e0 }"
>>> .Tcl(.Tcl.args(f))
>> Error in structure(.External(.C_dotTcl, ...), class =
"tclObj") :
>> [tcl] invalid command name " R_call 0x80e29e2e0 ".
>
> That's because passing an R function to a Tcl call converts it into a
> command string (e.g. { R_call 0x80e29e2e0 }) to be evaluated as a whole:
>
> f <- function() message('Hello from R from Tcl from R!')
> tcl('eval', f)
> # Hello from R from Tcl from R!
> # <Tcl>
>
> (Alternatively, .Tcl(.Tcl.callback(f)), because that doesn't wrap the
> string into {}. .Tcl.args(f), which does wrap, makes Tcl interpret that
> as a single command, which is results in an error, because "R_call
> whatever" is, indeed, not a command.)
>
> If you want to call it yourself, you have to separate R_call from its
> argument. Be careful, because passing the wrong pointer to R_call will
> crash the process:
>
> .Tcl.callback(f)
> # [1] "R_call 0x563e6e10b900"
> tcl('R_call', '0x563e6e10b900')
> # Hello from R from Tcl from R!
> # <Tcl>
> tcl('R_call')
> #
> # *** caught segfault ***
> # address (nil), cause 'memory not mapped'
> # ...
>
>> Is there a more detailed guide than help(TclInterface)?
>
> As far as I can tell, the R-Tcl/Tk interface is not well documented,
> but here are two R News articles providing some more information with
> examples:
>
> https://cran.r-project.org/doc/Rnews/Rnews_2001-3.pdf#section*.69
> https://cran.r-project.org/doc/Rnews/Rnews_2002-3.pdf#section*.54
>
> "Programming Graphical User Interfaces in R" by Michael F.
Lawrence
> John Verzani (ISSN 978-1-4398-5683-3) also provides some information.
> After that, I'm afraid you'll have to resort to source code diving.
>
--
John Fox, Professor Emeritus
McMaster University
Hamilton, Ontario, Canada
web: https://socialsciences.mcmaster.ca/jfox/