Skip to content
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

document __init__ #9240

Merged
merged 1 commit into from
Dec 3, 2014
Merged
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
58 changes: 57 additions & 1 deletion doc/manual/modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ on every Julia startup. Alternatively, the module load path can be
extended by defining the environment variable JULIA_LOAD_PATH.


Miscellaneous details
Namespace miscellanea
---------------------

If a name is qualified (e.g. ``Base.sin``), then it can be accessed even if
Expand All @@ -247,3 +247,59 @@ global assignment is always module-local.
A variable can be "reserved" for the current module without assigning to
it by declaring it as ``global x`` at the top level. This can be used to
prevent name conflicts for globals initialized after load time.

Module initialization and precompilation
----------------------------------------

Large modules can take several second to load because executing all of
the statements in a module often involves compiling a large amount of
code. However, Julia is progressively gaining more ability to cache
the parsed and compiled binary image of a package. Currently, this
requires one to recompile Julia after modifying the file
``base/userimg.jl`` to require the desired modules, but in a future
version of Julia the module caching will be simpler and more
automated. In order to make your module work with precompilation,
however, you may need to change your module to explicitly separate any
initialization steps that must occur at *runtime* from steps that can
occur at *compile time*. For this purpose, Julia allows you to define
an ``__init__()` function in your module that executes any
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a missing backtick here.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like it does. Fixed in 9743a99

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want, you can fix such issues yourself, even without mucking with the git command line, because github provides a Web UI to create pull requests if you click the pencil button above a file.

initialization steps that must occur at runtime.

In particular, if you define a ``function __init__()`` in a module,
then Julia will call ``__init__()`` immediately *after* the module is
loaded (e.g., by ``import``, ``using``, or ``require``) at runtime for
the *first* time (i.e., ``__init__`` is only called once, and only
after all statements in the module have been executed). Because it is
called after the module is fully imported, any submodules or other
imported modules have their ``__init__`` functions called *before* the
``__init__`` of the enclosing module.

Two typical uses of ``__init__`` are calling runtime initialization
functions of external C libraries and initializing global constants
that involve pointers returned by external libraries. For example,
suppose that we are calling a C library ``libfoo`` that requires us
to call a ``foo_init()`` initialization function at runtime. Suppose
that we also want to define a global constant ``foo_data_ptr`` that
holds the return value of a ``void *foo_data()`` function defined by
``libfoo`` — this constant must be initialized at runtime (not at compile
time) because the pointer address will change from run to run. You
could accomplish this by defining the following ``__init__`` function
in your module:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I think this should be two colons.


function __init__()
ccall((:foo_init,:libfoo), Void, ())
global const foo_data_ptr = ccall((:foo_data,:libfoo), Ptr{Void}, ())
end

(Notice that it is perfectly possible to define a global constant inside
a function like ``__init__``; this is one of the advantages of using a
dynamic language.) Obviously, any other constant in your module that
depends on ``foo_data_ptr`` would also have to be initialized in ``__init__``.

Constants involving most Julia objects that are not produced by
``ccall`` do not need to be placed in ``__init__``: their definitions
can be precompiled and loaded from the cached module image. (This
includes complicated heap-allocated objects like arrays and
dictionaries.) However, any routine that returns a raw pointer value
must be called at runtime for precompilation to work. This includes
the Julia functions ``cfunction`` and ``pointer``.