summaryrefslogtreecommitdiff
path: root/devdocs/elisp/module-initialization.html
blob: b5cc84fc7614dcc0d9264b06fe829635677b7975 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 <h4 class="subsection"> Module Initialization Code</h4>  <p>Begin your module by including the header file <samp>emacs-module.h</samp> and defining the GPL compatibility symbol: </p> <div class="example"> <pre class="example">#include &lt;emacs-module.h&gt;

int plugin_is_GPL_compatible;
</pre>
</div> <p>The <samp>emacs-module.h</samp> file is installed into your system’s include tree as part of the Emacs installation. Alternatively, you can find it in the Emacs source tree. </p> <p>Next, write an initialization function for the module. </p> <dl> <dt id="emacs_module_init">Function: <em>int</em> <strong>emacs_module_init</strong> <em>(struct emacs_runtime *<var>runtime</var>)</em>
</dt> <dd>
<p>Emacs calls this function when it loads a module. If a module does not export a function named <code>emacs_module_init</code>, trying to load the module will signal an error. The initialization function should return zero if the initialization succeeds, non-zero otherwise. In the latter case, Emacs will signal an error, and the loading of the module will fail. If the user presses <kbd>C-g</kbd> during the initialization, Emacs ignores the return value of the initialization function and quits (see <a href="quitting">Quitting</a>). (If needed, you can catch user quitting inside the initialization function, see <a href="module-misc#should_005fquit">should_quit</a>.) </p> <p>The argument <var>runtime</var> is a pointer to a C <code>struct</code> that includes 2 public fields: <code>size</code>, which provides the size of the structure in bytes; and <code>get_environment</code>, which provides a pointer to a function that allows the module initialization function access to the Emacs environment object and its interfaces. </p> <p>The initialization function should perform whatever initialization is required for the module. In addition, it can perform the following tasks: </p> <dl compact>  <dt>Compatibility verification</dt> <dd>
<p>A module can verify that the Emacs executable which loads the module is compatible with the module, by comparing the <code>size</code> member of the <var>runtime</var> structure with the value compiled into the module: </p> <div class="example"> <pre class="example">int
emacs_module_init (struct emacs_runtime *runtime)
{
  if (runtime-&gt;size &lt; sizeof (*runtime))
    return 1;
}
</pre>
</div> <p>If the size of the runtime object passed to the module is smaller than what it expects, it means the module was compiled for an Emacs version newer (later) than the one which attempts to load it, i.e. the module might be incompatible with the Emacs binary. </p> <p>In addition, a module can verify the compatibility of the module <acronym>API</acronym> with what the module expects. The following sample code assumes it is part of the <code>emacs_module_init</code> function shown above: </p> <div class="example"> <pre class="example">  emacs_env *env = runtime-&gt;get_environment (runtime);
  if (env-&gt;size &lt; sizeof (*env))
    return 2;
</pre>
</div> <p> This calls the <code>get_environment</code> function using the pointer provided in the <code>runtime</code> structure to retrieve a pointer to the <acronym>API</acronym>’s <em>environment</em>, a C <code>struct</code> which also has a <code>size</code> field holding the size of the structure in bytes. </p> <p>Finally, you can write a module that will work with older versions of Emacs, by comparing the size of the environment passed by Emacs with known sizes, like this: </p> <div class="example"> <pre class="example">  emacs_env *env = runtime-&gt;get_environment (runtime);
  if (env-&gt;size &gt;= sizeof (struct emacs_env_26))
    emacs_version = 26;  /* Emacs 26 or later.  */
  else if (env-&gt;size &gt;= sizeof (struct emacs_env_25))
    emacs_version = 25;
  else
    return 2; /* Unknown or unsupported version.  */
</pre>
</div> <p>This works because later Emacs versions always <em>add</em> members to the environment, never <em>remove</em> any members, so the size can only grow with new Emacs releases. Given the version of Emacs, the module can use only the parts of the module <acronym>API</acronym> that existed in that version, since those parts are identical in later versions. </p> <p><samp>emacs-module.h</samp> defines a preprocessor macro <code>EMACS_MAJOR_VERSION</code>. It expands to an integer literal which is the latest major version of Emacs supported by the header. See <a href="version-info">Version Info</a>. Note that the value of <code>EMACS_MAJOR_VERSION</code> is a compile-time constant and does not represent the version of Emacs that is currently running and has loaded your module. If you want your module to be compatible with various versions of <samp>emacs-module.h</samp> as well as various versions of Emacs, you can use conditional compilation based on <code>EMACS_MAJOR_VERSION</code>. </p> <p>We recommend that modules always perform the compatibility verification, unless they do their job entirely in the initialization function, and don’t access any Lisp objects or use any Emacs functions accessible through the environment structure. </p> </dd> <dt>Binding module functions to Lisp symbols</dt> <dd><p>This gives the module functions names so that Lisp code could call it by that name. We describe how to do this in <a href="module-functions">Module Functions</a> below. </p></dd> </dl> </dd>
</dl><div class="_attribution">
  <p class="_attribution-p">
    Copyright &copy; 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br>
    <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Module-Initialization.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Module-Initialization.html</a>
  </p>
</div>