New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reload(): Unload dynamic libraries #119

Closed
wch opened this Issue Jul 23, 2012 · 3 comments

Comments

Projects
None yet
1 participant
@wch
Member

wch commented Jul 23, 2012

Presently, to unload and reload a compiled library during development, you can do this:

library.dynam.unload('c_test', '~/R-dev/c_test/')
install()

test_func()

It would be good to automate the unloading process by making reload() automatically do it. The dynLibs() function might be helpful for finding the path of the loaded library.

This should also be tested on Windows and Linux. According to ?dyn.load, unloading won't work on Solaris.

@wch

This comment has been minimized.

Member

wch commented Jul 23, 2012

Normally, the dynamic library has the same name as the package, so this should work:

pkgname <- 'c_test'
pkgpath <- system.file(package=pkgname)
library.dynam.unload(pkgname, pkgpath)

But in case there are multiple libraries in that path, it might be better to search the .dynLibs() for all libraries that contain the pkgpath:

dynlib_paths <- vapply(.dynLibs(), function(x) x[["path"]], character(1))

# List all the libraries under that path
# Need to be careful since the string matches anywhere, not just at the beginning
dynlib_paths[grepl(pkgpath, dynlib_paths, fixed=TRUE)]

It appears that most packages have library files with the same name as the package. But there are some exceptions. A find in my library path turns up a few:

./data.table/libs/x86_64/datatable.so
./data.table/libs/x86_64/datatable.so.dSYM/Contents/Resources/DWARF/datatable.so
./rgl/libs/i386/aglrgl.so
./rgl/libs/i386/aglrgl.so.dSYM/Contents/Resources/DWARF/aglrgl.so
./rgl/libs/i386/rgl.so
./rgl/libs/i386/rgl.so.dSYM/Contents/Resources/DWARF/rgl.so
./rgl/libs/x86_64/aglrgl.so
./rgl/libs/x86_64/aglrgl.so.dSYM/Contents/Resources/DWARF/aglrgl.so
./rgl/libs/x86_64/rgl.so
./rgl/libs/x86_64/rgl.so.dSYM/Contents/Resources/DWARF/rgl.so

@wch

This comment has been minimized.

Member

wch commented Jul 24, 2012

This code should unload all the loaded libraries from a given package:

library(bitops)
# Show what's loaded
.dynLibs()

pkgname <- 'bitops'
# Get installation path for the package
pkgpath <- system.file(package=pkgname)

# Get a vector of paths for all loaded libs
dynlib_paths <- vapply(.dynLibs(), function(x) x[["path"]], character(1))

# Find which of the lib paths start with pkgpath
pkgmatch <- pkgpath == substr(dynlib_paths, 1, nchar(pkgpath))

# Get matching lib paths and strip off leading path and extension (.so or .dll)
libnames <- sub("\\.[^\\.]*$", "", basename(dynlib_paths[pkgmatch]))

library.dynam.unload(libnames, pkgpath)

# Show what's loaded
.dynLibs()

# We can also unload the package
detach(paste("package", pkgname, sep =":"), character.only = TRUE, force = TRUE, unload = TRUE)

I tried experimenting with plyr, but it appears that it can't be unloaded because devtools depends on testthat, which depends on stringr, which depends on plyr.

Also, it appears that some packages are nice enough to have an .onUnload function that does it automatically:

> MASS:::.onUnload
function (libpath) 
library.dynam.unload("MASS", libpath)
<environment: namespace:MASS>
@wch

This comment has been minimized.

Member

wch commented Aug 13, 2012

Implemented in #137.

@wch wch closed this Aug 13, 2012

@lock lock bot locked and limited conversation to collaborators Sep 19, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.