cwal

whcl: Loadable Modules API
Login

whcl: Loadable Modules API

(⬑Central whcl Documentation Hub) (⬑API Index)

Loadable Modules API

Available Modules

Work is underway to port the loadable modules from s2, one significant difference being that an approach was developed for whcl which allows most modules to be compiled in to whcl without requiring that they be initialized (and therefore do not have an initialization-time performance or memory cost). Thus modules are compiled directly in to whcl when possible, falling back to DLL builds only when necessary.

The current list of available modules is (in alphabetical order):

Loading External DLLs

WHCL is capable of loading new features from DLL files (known as "shared objects," or "SO's," in Unix parlance). The base interface for doing so is:

decl module [whcl load-module "/path/to/the.dll"]

Loadable modules do not typically install themselves anywhere, and instead return a single value to the caller. That value is typically an object which contains the module's functions, but any single value is legal. Some modules may return only a single function.

The loader has a second, more obscure, call form as well:

whcl load-module "/path/to/the.dll" "entry_point_symbol_name"

When modules are compiled standalone (one module per DLL), this form is unnecessary. When multiple modules are compiled into a single DLL, the symbol name is the name of the module, e.g. my_module. The DLL loader looks for a symbol in the DLL named whcl_module_my_module and, if found, uses it to initialize the module loader. For the gory details, see the API documentation for WHCL_MODULE_REGISTER and friends in whcl.h or (depending on the whcl build you are using) libwhcl.h.

Creating Loadable Modules

Creating a new loadable module is as simple as...

A documented sample module can be found at /dir/whcl/mod/sample/. The build process used by the canonical whcl source tree "rather involved" (arguably over-engineered) and the specifics of building DLLs are platform-dependent, so are out of scope here. The sample plugin should give a good idea of how to get started, though.

Adding New Modules to the Canonical Source Tree

(This section is more of a reminder to self than end-user docs!)

The build rules for the in-tree modules are generated on-demand via a shell script. They automatically add any modules for which the file whcl/mod/MODULE/module-def.make exists. Each module's directory name must be the module's symbolic name - the one client code will load it with.

The module-def.make file gets imported by the build process and tells the build system all that it needs to know by way of the following variables:

Before include'ing module-def.make, the build rules first clear all of the various module.xxx vars and set:

The build process has to prefix all of the module-related var names with WHCL because (1) the source tree uses a single monolithic build file to get optimal parallel build support and (2) without a prefix, the names collide with modules from the s2 build (which do not have such a prefix because this build approach was not yet foreseen when that code was written).

Some not-quite-trivial module-def.make files make use of more state provided by the higher-level makefile. In principle and module makefile may safely use any vars set by the top-level main makefile, the auto.make, and make-whcl.make.

To build a module as a built-in, the module must have either static_module.c or static_module.cpp and that file must directly #include all other C/C++ files it requires. This simplifies the whcl build process by having only a single file per module with a well-defined name, at the cost of increased compile time when only a subset of the #included files changes. See any of the existing modules for examples of how these are set up.

Module API Limitations

Over the years this same module API has seen a great deal of service in the s2 project and its predecessors. Based on that experience, the known shortcomings of this API are...

... that's been the only genuine annoyance so far.