Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,9 @@ static void interpret_symbol_arg(jl_codectx_t &ctx, native_sym_arg_t &out, jl_va
arg1 = update_julia_type(ctx, arg1, (jl_value_t*)jl_voidpointer_type);
jl_ptr = emit_unbox(ctx, ctx.types().T_ptr, arg1, (jl_value_t*)jl_voidpointer_type);
}
else if (jl_is_cpointer_type(jl_typeof(ptr))) {
fptr = *(void(**)(void))jl_data_ptr(ptr);
}
else {
out.gcroot = ptr;
if (jl_is_tuple(ptr) && jl_nfields(ptr) == 1) {
Expand Down Expand Up @@ -633,9 +636,6 @@ static void interpret_symbol_arg(jl_codectx_t &ctx, native_sym_arg_t &out, jl_va
}
}
}
else if (jl_is_cpointer_type(jl_typeof(ptr))) {
fptr = *(void(**)(void))jl_data_ptr(ptr);
}
else if (jl_is_tuple(ptr) && jl_nfields(ptr) > 1) {
jl_value_t *t0 = jl_fieldref(ptr, 0);
if (jl_is_symbol(t0))
Expand Down
35 changes: 15 additions & 20 deletions src/runtime_intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,6 @@ JL_DLLEXPORT jl_value_t *jl_atomic_fence(jl_value_t *order_sym)
JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty)
{
JL_TYPECHK(cglobal, type, ty);
JL_GC_PUSH1(&v);
jl_value_t *rt =
ty == (jl_value_t*)jl_nothing_type ? (jl_value_t*)jl_voidpointer_type : // a common case
(jl_value_t*)jl_apply_type1((jl_value_t*)jl_pointer_type, ty);
Expand All @@ -643,24 +642,16 @@ JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty)
if (!jl_is_concrete_type(rt))
jl_error("cglobal: type argument not concrete");

if (jl_is_pointer(v))
return jl_bitcast(rt, v);

if (jl_is_tuple(v) && jl_nfields(v) == 1)
v = jl_fieldref(v, 0);

if (jl_is_pointer(v)) {
v = jl_bitcast(rt, v);
JL_GC_POP();
return v;
}

char *f_lib = NULL;
jl_value_t *f_lib = NULL;
JL_GC_PUSH2(&v, &f_lib);
if (jl_is_tuple(v) && jl_nfields(v) > 1) {
jl_value_t *t1 = jl_fieldref(v, 1);
if (jl_is_symbol(t1))
f_lib = jl_symbol_name((jl_sym_t*)t1);
else if (jl_is_string(t1))
f_lib = jl_string_data(t1);
else
JL_TYPECHK(cglobal, symbol, t1)
f_lib = jl_fieldref(v, 1);
v = jl_fieldref(v, 0);
}

Expand All @@ -672,14 +663,18 @@ JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty)
else
JL_TYPECHK(cglobal, symbol, v)

if (!f_lib)
f_lib = (char*)jl_dlfind(f_name);

void *ptr;
jl_dlsym(jl_get_library(f_lib), f_name, &ptr, 1);
if (f_lib) {
ptr = jl_lazy_load_and_lookup(f_lib, f_name);
}
else {
void *handle = jl_get_library((char*)jl_dlfind(f_name));
jl_dlsym(handle, f_name, &ptr, 1);
}
JL_GC_POP();

jl_value_t *jv = jl_gc_alloc(jl_current_task->ptls, sizeof(void*), rt);
*(void**)jl_data_ptr(jv) = ptr;
JL_GC_POP();
return jv;
}

Expand Down
23 changes: 17 additions & 6 deletions stdlib/Libdl/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ mktempdir() do dir
end

## Tests for LazyLibrary
@testset "LazyLibrary" begin; mktempdir() do dir
@testset "LazyLibrary" begin
lclf_path = joinpath(private_libdir, "libccalllazyfoo.$(Libdl.dlext)")
lclb_path = joinpath(private_libdir, "libccalllazybar.$(Libdl.dlext)")

Expand All @@ -278,7 +278,7 @@ end
global lclf_loaded = false
global lclb_loaded = false

# We don't provide `dlclose()` on `LazyLibrary`'s, you have to manage it yourself:
# We don't provide `dlclose()` on `LazyLibrary`'s since it is dangerous, you have to manage it yourself:
function close_libs()
global lclf_loaded = false
global lclb_loaded = false
Expand All @@ -294,8 +294,12 @@ end
@test !any(contains.(dllist(), lclb_path))
end

global libccalllazyfoo = LazyLibrary(lclf_path; on_load_callback=() -> global lclf_loaded = true)
global libccalllazybar = LazyLibrary(lclb_path; dependencies=[libccalllazyfoo], on_load_callback=() -> global lclb_loaded = true)
let libccalllazyfoo = LazyLibrary(lclf_path; on_load_callback=() -> global lclf_loaded = true),
libccalllazybar = LazyLibrary(lclb_path; dependencies=[libccalllazyfoo], on_load_callback=() -> global lclb_loaded = true)
eval(:(const libccalllazyfoo = $libccalllazyfoo))
eval(:(const libccalllazybar = $libccalllazybar))
end
Core.@latestworld

# Creating `LazyLibrary` doesn't actually load anything
@test !lclf_loaded
Expand All @@ -308,7 +312,8 @@ end
close_libs()

# Test that the library gets loaded when you use `ccall()`
@test ccall((:bar, libccalllazybar), Cint, (Cint,), 2) == 6
compiled_bar() = ccall((:bar, libccalllazybar), Cint, (Cint,), 2)
@test ccall((:bar, libccalllazybar), Cint, (Cint,), 2) == compiled_bar() == 6
@test lclf_loaded
@test lclb_loaded
close_libs()
Expand All @@ -324,11 +329,17 @@ end
@test lclf_loaded
close_libs()

# Test that `cglobal()` works, both compiled and runtime emulation
compiled_cglobal() = cglobal((:bar, libccalllazybar))
@test cglobal((:bar, libccalllazybar)) === compiled_cglobal() === dlsym(dlopen(libccalllazybar), :bar)
@test lclf_loaded
close_libs()

# Test that we can use lazily-evaluated library names:
libname = LazyLibraryPath(private_libdir, "libccalllazyfoo.$(Libdl.dlext)")
lazy_name_lazy_lib = LazyLibrary(libname)
@test dlpath(lazy_name_lazy_lib) == realpath(string(libname))
end; end
end

@testset "Docstrings" begin
@test isempty(Docs.undocumented_names(Libdl))
Expand Down