Ccall of entry point name vs tuple of entry point and library

As background, I have been working on modifying some of the RCall.jl code to isolate the boxing/unboxing code for R’s internal representations of objects. The idea is to write Julia code that can be compiled to a shared library and called from R.

I spent an inordinate amount of time fussing about how to determine the exact version of the libR shared library (e.g. libR.so) in use by the R process that loads the Julia code. Then I re-read the documentation for Julia’s ccall (Pro Tip: When you are wondering how something works, try reading the documentation) and realized that I could call, e.g. the C function Rf_xlength, which returns the length of an R object, as len = ccall(:Rf_xlength, my_R_object) instead of len = ccall((:Rf_xlength, libR), my_R_object).

And it works! (One of the delightful things about programming in Julia is how often “it just works”.) So my question is, am I giving up performance by specifying only the entry point. I haven’t tracked down the code that implements this yet but I imagine that there is some kind of lookup through the entry point names in the currently loaded shared libraries. Are the results cached so that further calls to Rf_xlength don’t require the lookup?

2 Likes

You aren’t giving up any performance, but you may sacrifice easy compatibility with Windows, which doesn’t have a “default” handle for us to search for symbols in.

Any suggestions of how to handle the situation in Windows? In R I can evaluate R.home() and get the directory whose subdirectory lib contains the libR of interest, but I feel that somehow getting that information to the Julia shared library would involve a lot of contortions.

Perhaps you can loop through the Libc.Libdl.dllist() and find the R library there? Then pick up the pointer with dlsym (e.g. in __init__), and use that in the ccall?