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?
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 (
juliacwith the--trimoption). 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.Callinterface or the.Externalinterface (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
Cstruct calledSEXPREC(the pointer type is calledSEXP) and the return value must also be anSEXP. This the basic boxing/unboxing strategy in R. Doing the unboxing in Julia is straightforwardly accomplished by thercopymethods from this package (i.e.RCall.jl). The boxing inRCall.jlis accomplished by methods forsexp. 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 iswhich causes allocation in the inner calls to
sexp, pushes and pops from a stack in the R environment in theprotectandunprotectcalls, and requires access to certain global constants insetclass!. These Julia function all eventually end up calling C functions in libR. Especially the allocation and theprotect/unprotectmust 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.jland files insrc/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 thatsrc/Const.jlcontains both@load_constand@load_const_embeddedmacros that the answer is yes because@load_const_embeddeddoesn't specifylibR.So would creating Julia code to unbox the arguments from
.Callor.Externaland boxing the result be as simple as creating aRconversionBasepackage with some of the code fromsrc/types.jl,src/Const.jl,src/methods.jland the files insrc/convertthen using that package to provide boxing/unboxing forRCall.jland for Julia code to be called from R packages?