When doing the following in 0.7:
module Foo end
ERROR: ArgumentError: Module Foo not found in current path.
Run `Pkg.add("Foo")` to install the Foo package.
I found I could do
using Main.Foo instead, but is there a way to avoid this? My usecase is CxxWrap.jl, where modules are created using a function call instead of by regularly loading a package.
That module is defined in
Main, which is the module where one executes all the expressions of the REPL, and so on. Just call it by
Main.Foo or simply
.Foo if you are still in
To check on which module are you use
See also: Creating modules in Julia v0.7-alpha - #3 by Roger-luo
using .Foo is unambiguous and will just work in v0.6 and v0.7.
Thanks, missed the other topic about this. So my next question is, is it a good idea to still load modules in
Main then? There is now a
__toplevel__ module in Base:
# This is used as the current module when loading top-level modules.
# It has the special behavior that modules evaluated in it get added
# to the loaded_modules table instead of getting bindings.
But when I use that (i.e.
@eval Base.__toplevel__ module Foo end), the module is invisible. Since the default behavior is no longer to load modules into
Main, it seems that for CxxWrap I should also avoid doing that.
The normal code-loading logic requires (!) modules to (seem to) be defined by files in
LOAD_PATH etc. I suspect that is a mistake, but in any case one can get around this as follows:
# reverse lookup of pkg id
# (We can't simply use the module as an index because it's not bound)
for (u,v) in Base.loaded_modules
(Symbol(v) == f) && return u
# substitute for `import Foo`:
Foo = Base.loaded_modules[findmod(:Foo)]
# substitute for `using Foo`:
ccall(:jl_module_using, Cvoid, (Any, Any), MyModule,
Messing around with
Base.loaded_modules is not recommended and may break at any time in a 1.x release. I don’t really understand the use case for CxxWrap well enough to give advice on a better way to do this. @barche, can you elaborate?
The problematic code is this:
function create_module(name::String, parent::Module)
return Core.eval(parent, :(module $(Symbol(name)) end))
This gets called by
wrap_modules(cpp_lib) to create a Julia module for every module declared on the C++ side and compiled into the
cpp_lib. The parent module is
Main by default, so in Julia 0.7 using the generated modules would require the leading “.”.
I think @Ralph_Smith provided a viable workaround, but on further reflection I think using the following approach is better:
This approach is already supported as an alternative, but I intend to make it the only way to declare a module. That way no hacking into Julia internals is needed and everything works just like a normal Julia module. The only downside is that it’s a bit more verbose when there are multiple modules in the C++ lib, but in practice it’s often required to add some Julia code to the modules, so manually declaring the module is the only way to go anyway.