Bug 14939 - Add tclObj.raw method for converting raw vectors to tclObj in package tcltk
Add tclObj.raw method for converting raw vectors to tclObj in package tcltk
Status: CLOSED FIXED
Product: R
Classification: Unclassified
Component: Wishlist
R 2.15.0
All All
: P5 enhancement
Assigned To: R-core
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2012-06-06 04:24 UTC by Charlie Friedemann
Modified: 2012-06-15 14:15 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Charlie Friedemann 2012-06-06 04:24:28 UTC
I was wondering if it would be possible to add another C routine to be called by as.TclObj for raw vectors. Right now, as.raw() is supported for objects of type "tclObj" (IIRC this change was made in 2.9 after someone requested it), however there is no corresponding C routine for converting raw vectors into tclObj.  

I suppose the best way to do this is to create a new C routine in the tcltk package analogous to the other RObject to Tcl object routines: RTcl_ObjFromRawVector. Create a new tclObj pointer, use Tcl_NewByteArrayObj() from the Tcl C API to create a byte array of the same length as the input raw vector, and then loop through the RAWSXP object assigning each element in the vector to the Tcl byte array. I'd be happy to submit code for this patch if requested.

This would be extremely helpful. I am using tcl binary sockets and this functionality would allow me to both read and write raw vectors directly from/to Tcl. I can only read raw vectors directly at the moment and have to use strings to get a raw vector into Tcl.

There's also the possibility that this has been attempted and for some reason it didn't work, but I don't know why that would be the case. Thank you for your consideration!

Charlie
Comment 1 Charlie Friedemann 2012-06-14 02:28:31 UTC
My proposed patch is below. I have built R-devel successfully with these proposed changes, and all of the recommended packages check successfully (including tcltk). All of these changes are made in tcltk:

Add the following routine to tcltk.c, located in src/library/tcltk/src:

SEXP RTcl_ObjFromRawVector(SEXP args)
{
    int count;
    Tcl_Obj *tclobj; 
    SEXP val; 

    val = CADR(args);
    
    count = length(val);
    tclobj = Tcl_NewByteArrayObj(RAW(val), count);

    return makeRTclObject(tclobj);
}

Declare this new routine in src/library/tcltk/src/tcltk.h:

SEXP RTcl_ObjFromRawVector(SEXP args); // added at line 67

Register this routine for export in src/library/tcltk/src/init.c:

{"RTcl_ObjFromRawVector", (DL_FUNC) &RTcl_ObjFromRawVector, 1}, // added at line 51

And finally, alter the as.tclObj routine in src/library/tcltk/R/Tk.R:

raw = .External("RTcl_ObjFromRawVector", x, PACKAGE="tcltk"), # added at line 280

The following demonstrates the new functionality:

> library(tcltk)
> rw <- serialize(women,NULL)
> tobj
<Tcl> X
 
> tclvalue(tobj)
[1] "X\n"

> identical(unserialize(as.raw(tobj)), women)
[1] TRUE

I would be extremely grateful if someone could add this patch to the next release. Thank you, and I really appreciate all the work you guys do!
Comment 2 Charlie Friedemann 2012-06-14 02:30:59 UTC
Oh, one thing I forgot to add is that the "drop" argument in as.tclObj is not used, as it doesn't make sense in the context of a Tcl ByteArray.
Comment 3 Peter Dalgaard 2012-06-14 12:18:42 UTC
The patch looks sane, but I can't make sense of the example. Where is "rw" used and where does "tobj" come from??

This might go into R-devel, but not 2.15.1 which is entering code freeze tomorrow.
Comment 4 Charlie Friedemann 2012-06-14 13:43:13 UTC
(In reply to comment #3)
> The patch looks sane, but I can't make sense of the example. Where is "rw" used
> and where does "tobj" come from??
> 
> This might go into R-devel, but not 2.15.1 which is entering code freeze
> tomorrow.

Sorry, I forgot a line in the example.  It should read:

> library(tcltk)
> rw <- serialize(women,NULL)
> tobj <- as.tclObj(rw) #needed this line
> tobj
<Tcl> X

> tclvalue(tobj)
[1] "X\n"

> identical(unserialize(as.raw(tobj)), women)
[1] TRUE
Comment 5 Peter Dalgaard 2012-06-15 14:15:03 UTC
Now in R-devel.

Incidentally, it already worked to do

library(tcltk)
x <- serialize(women, NULL)
y <- as.integer(x)
z <- tcl("binary", "format", "c*", y)
unserialize(as.raw(z))

but now also

zz <- as.tclObj(x)
unserialize(as.raw(zz)

which is of course neater and more efficient. The symmetry was worth having, anyways.