I would like to make a package extension that loads if JLD.jl is loaded. I got the code below to work in the REPL, but when I make Abc the main package and JLDExt the extension (and remove the dots in front of the package names) I get the warning “type JLDExt.JLDAb not present in workspace; reconstructing” and the deserialization fails.
module Abc
export Ab
struct Ab
a
end
end # module Abc
#----------------------
module JLDExt
using ..Abc, JLD
import JLD.writeas
import JLD.readas
export JLDAb
struct JLDAb
a
end
JLD.writeas(x::Ab) = writeas(JLDAb(x.a))
JLD.readas(x::JLDAb) = Ab(x.a)
end
#--------------------
using Test, .Abc, .JLDExt, JLD
@testset "JLD" begin
x = Ab(1)
fname = "/tmp/JLD_test.jld"
save(fname, "x", x)
@test load(fname)["x"] == x
end
I worked on this some more and it appears that new symbols defined in extensions are not normally visible from outside the extension. I have gotten things to work with an ugly solution at GitHub - GHTaarn/Abc.jl at fix_alpha that has the following Julia files:
module Abc
export Ab, JLDExt
struct Ab
a
end
function set_jldext()
global JLDExt
pause = 0.01
for t in 0:pause:2
JLDExt = Base.get_extension(@__MODULE__, :JLDExt)
!isnothing(JLDExt) && break
sleep(pause)
end
@info "JLDExt set to '$JLDExt'"
end
end # module Abc
module JLDExt
using Abc, JLD
import JLD.writeas
import JLD.readas
struct JLDAb
a
end
JLD.writeas(x::Ab) = writeas(JLDAb(x.a))
JLD.readas(x::JLDAb) = Ab(x.a)
function __init__()
@async Abc.set_jldext()
@info "Loaded JLDExt"
end
end
using Test, Abc, JLD
@testset "JLD" begin
sleep(0.1)
x = Ab(1)
fname = "/tmp/JLD_test.jld"
save(fname, "x", x)
@test load(fname)["x"] == x
end
Any suggestions on how to avoid the sleeps would be appreciated. Is there a callback for when a module is loaded or something that wait can be called on that triggers when a module is loaded?
After a good nights sleep, I discovered that the solution is really simple:
module Abc
export Ab, JLDExt
struct Ab
a
end
function set_jldext(m)
global JLDExt = m
@info "JLDExt set to '$JLDExt'"
end
end # module Abc
module JLDExt
using Abc, JLD
import JLD.writeas
import JLD.readas
struct JLDAb
a
end
JLD.writeas(x::Ab) = writeas(JLDAb(x.a))
JLD.readas(x::JLDAb) = Ab(x.a)
function __init__()
Abc.set_jldext(JLDExt)
@info "Loaded JLDExt"
end
end
using Test, Abc, JLD
@testset "JLD" begin
x = Ab(1)
fname = "/tmp/JLD_test.jld"
save(fname, "x", x)
@test load(fname)["x"] == x
end