-
Notifications
You must be signed in to change notification settings - Fork 60
Description
Development versions of Julia-1.12 and 1.13 provide compilation of Julia code to a shared library and ways to shrink the size of the binary (juliac
with the --trim
option). One attractive application of this capability is to write compute-intensive parts of R packages in Julia instead of going the C/Fortran/C++ route. I think the preferred interface from R for such Julia code would be the .Call
interface or the .External
interface (https://cran.r-project.org/doc/manuals/R-exts.html#Interface-functions-_002eCall-and-_002eExternal-1).
For each of these interfaces the arguments are passed as pointers to a C
struct called SEXPREC
(the pointer type is called SEXP
) and the return value must also be an SEXP
. This the basic boxing/unboxing strategy in R. Doing the unboxing in Julia is straightforwardly accomplished by the rcopy
methods from this package (i.e. RCall.jl
). The boxing in RCall.jl
is accomplished by methods for sexp
. But these methods use functions from libR that manipulate locations in the R environment to do things like allocate storage within R and mark it as protected from garbage collection. An example in https://juliainterop.github.io/RCall.jl/dev/custom/#Julia-to-R-direction is
import RCall: sexp, protect, unprotect, setclass!, RClass
function sexp(::Type{RClass{:Bar}}, f::Foo)
r = protect(sexp(Dict(:x => f.x, :y => f.y)))
setclass!(r, sexp("Bar"))
unprotect(1)
r
end
which causes allocation in the inner calls to sexp
, pushes and pops from a stack in the R environment in the protect
and unprotect
calls, and requires access to certain global constants in setclass!
. These Julia function all eventually end up calling C functions in libR. Especially the allocation and the protect/unprotect
must manipulate global locations in the environment of the R process calling the Julia code.
If a library was compiled from Julia code that contained code similar to src/types.jl
, src/Const.jl
and files in src/convert
, and that library was opened by an R process, would the calls to libR functions be resolved against the copy of libR in use by the R process? It seems from the way that src/Const.jl
contains both @load_const
and @load_const_embedded
macros that the answer is yes because @load_const_embedded
doesn't specify libR
.
So would creating Julia code to unbox the arguments from .Call
or .External
and boxing the result be as simple as creating a RconversionBase
package with some of the code from src/types.jl
, src/Const.jl
, src/methods.jl
and the files in src/convert
then using that package to provide boxing/unboxing for RCall.jl
and for Julia code to be called from R packages?