Custom Conversion
RCall supports an API for implicitly converting between R and Julia objects by means of rcopy and RObject.
To illustrate the idea, we consider the following Julia type
type Foo
x::Float64
y::String
endfoo = Foo(1.0, "hello")Julia to R direction
The function RCall.sexp has to be overwritten to allow Julia to R conversion. sexp function takes a julia object and returns an SEXP object (pointer to [Sxp]).
import RCall.sexp
function sexp(f::Foo)
r = protect(sexp(Dict(:x => f.x, :y => f.y)))
setclass!(r, sexp("Bar"))
unprotect(1)
r
end
roo = RObject(foo)
nothing # hideRemark: RCall.protect and RCall.unprotect should be used to protect SEXP from being garbage collected.
R to Julia direction
The function rcopy and rcopytype are responsible for conversions of this direction. First we define an explicit converter for VecSxp (SEXP for list)
import RCall.rcopy
function rcopy(::Type{Foo}, s::Ptr{VecSxp})
Foo(rcopy(Float64, s[:x]), rcopy(String, s[:y]))
endrcopy (generic function with 97 methods)The convert function will dispatch the corresponding rcopy function when it is found.
rcopy(Foo, roo)
convert(Foo, roo) # calls `rcopy`
Foo(roo)
nothing # hideTo allow the automatic conversion via rcopy(roo), the R class Bar has to be registered.
import RCall: RClass, rcopytype
rcopytype(::Type{RClass{:Bar}}, s::Ptr{VecSxp}) = Foo
boo = rcopy(roo)
nothing # hideUsing @rput and @rget is seamless
boo.x = 2.0
@rput boo
R"""
boo["x"]
"""R"""
boo["x"] = 3.0
"""
@rget boo
boo.xNested conversion
l = R"list(boo = boo, roo = $roo)"rcopy(l)