Skip to content

Commit

Permalink
Add do-block support for dlopen()
Browse files Browse the repository at this point in the history
  • Loading branch information
staticfloat committed May 12, 2019
1 parent bfcf172 commit a3173d7
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 0 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ Standard library changes
(environment, flags, working directory, etc) if `x` is the first interpolant and errors
otherwise ([#24353]).

#### Libdl

* `dlopen()` can now be invoked in `do`-block syntax, similar to `open()`.

#### LinearAlgebra

* The BLAS submodule no longer exports `dot`, which conflicts with that in LinearAlgebra ([#31838]).
Expand Down
27 changes: 27 additions & 0 deletions stdlib/Libdl/src/Libdl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,33 @@ function dlopen(s::AbstractString, flags::Integer = RTLD_LAZY | RTLD_DEEPBIND; t
return ret
end

"""
dlopen(f::Function, args...; kwargs...)
Wrapper for usage with `do` blocks to automatically close the dynamic library once
control flow leaves the `do` block scope.
# Example
```julia
vendor = dlopen("libblas") do lib
if Libdl.dlsym(lib, :openblas_set_num_threads; throw_error=false) !== nothing
return :openblas
else
return :other
end
end
```
"""
function dlopen(f::Function, args...; kwargs...)
hdl = nothing
try
hdl = dlopen(args...; kwargs...)
f(hdl)
finally
dlclose(hdl)
end
end

"""
dlopen_e(libfile::AbstractString [, flags::Integer])
Expand Down
12 changes: 12 additions & 0 deletions stdlib/Libdl/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,18 @@ let dl = C_NULL
end
end

# test do-block dlopen
Libdl.dlopen(abspath(joinpath(private_libdir, "libccalltest"))) do dl
fptr = Libdl.dlsym(dl, :set_verbose)
@test fptr !== nothing
@test_throws ErrorException Libdl.dlsym(dl, :foo)

fptr = Libdl.dlsym_e(dl, :set_verbose)
@test fptr != C_NULL
fptr = Libdl.dlsym_e(dl, :foo)
@test fptr == C_NULL
end

# test dlclose
# If dl is NULL, jl_dlclose should return -1 and dlclose should return false
# dlclose should return true on success and false on failure
Expand Down

0 comments on commit a3173d7

Please sign in to comment.