7
votes

Following up on this question here, I am having issues using dyn.load to load a shared library that is linked to a Rust dylib. I suspect it has something to do with where R is looking for the Rust dylib, but I have not found a way to specify another location than whatever the default is.

From R, I execute the following:

> dyn.load('src/test.so')

And receive this error message:

Error in dyn.load("src/test.so") : 
  unable to load shared object '/Users/Zelazny7/r-dev/rustr/src/test.so':
  dlopen(/Users/Zelazny7/r-dev/rustr/src/test.so, 6): Library not loaded: libglue.dylib
  Referenced from: /Users/Zelazny7/r-dev/rustr/src/test.so
  Reason: image not found

How do I load a shared library that depends on another shared library?

The documentation for dyn.load does not specify how to do this.

Update:

Thanks to shepmaster I was able to successfully build and import a shared library in R. The shared library was compiled in C and is itself linked to a Rust library. These were my steps:

  1. Compile shared Rust library
  2. Compile shared C library and link to the Rust library using the following command (in Windows as I'm at work this morning)

My directory contents:

C:\Users\gravesee\test>ls
rglue.dll  rglue.rs  rustr.c  treble.h

Compiling the final shared library:

gcc -shared -m64 -I"C:\Program Files\R\R-3.2.0\include" rustr.c -L"C:\Program Files\R\R-3.2.0\bin\x64" -lR -L. -lrglue -o test.dll

Loading the library in R:

> dyn.load("test.dll")
> is.loaded("triple")
[1] TRUE
> .Call("triple", as.integer(32))
The triple is 96
2

2 Answers

4
votes

The problem is going to boil down to the fact that your shared libraries are not in the directories that your system expects them to be by default.

There are a few tricks that you can use, 2 of which I was able to make work:

  1. Run R from the same directory you compiled the libraries.

  2. Set the LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OS X) before launching R.

    DYLD_LIBRARY_PATH=/path/to/rust/lib/ R
    
  3. You should be able to set the rpath when building the shared library.

    g++ -shared treble.cxx -o treble.so -L/tmp/ -Wl,-rpath,/tmp -lglue
    

    However, I wasn't able to get this to work nicely on OS X, so I'm not sure what I'm doing wrong.

  4. (OS X only) After building your C++ library, you can change the install name that refers to the original Rust library and include the absolute path:

    install_name_tool -change libglue.dylib /tmp/libglue.dylib treble.so
    

Basically, you will want to look up how to have shared libraries that depend on other shared libraries when multiple of those libraries do not exist in your default linker search paths.

Sources

Linking a dynamic library (libjvm.dylib) in Mac OS X (rpath issue)

Print rpath of executable on OSX

@executable_path, @load_path and @rpath

How do I modify the install name of a .dylib at build time

clang, change dependent shared library install name at link time

0
votes

Although the original answer is good, I put forward an alternative approach for this here.