.. default-domain:: chpl .. module:: DynamicLoading :synopsis: Support for dynamic loading in Chapel. DynamicLoading ============== **Usage** .. code-block:: chapel use DynamicLoading; or .. code-block:: chapel import DynamicLoading; .. warning:: Dynamic loading support is experimental and unstable. Support for dynamic loading in Chapel. .. note:: To ``use`` this module, the experimental procedure pointer feature must be activated. Do this by setting the ``config param`` named ``useProcedurePointers`` to ``true``. This module provides the ability to load a binary at runtime. Procedures contained in a dynamically loaded binary can be retrieved and called on any locale without compile-time knowledge of their names or locations. A hypothetical C binary could contain a procedure named ``foo``: .. code-block:: c // Compile with: 'cc -shared -fPIC -o TestBinary TestBinary.c' // // Your C compiler must support compiling a shared library as well // as generating "position independent code". If your compiler // offers some other way of preserving symbol tables (e.g., the // '-rdynamic' flag) for use with dynamic loading, you can compile // a regular executable with that flag as well. // #include void foo(void); void foo(void) { printf("Hello world from %s!\n", __FUNCTION__); } int main(void) { foo(); return 0; } This binary can be can be loaded in Chapel at runtime as follows: .. code-block:: chapel // Compile with: 'chpl Test.chpl -suseProcedurePointers=true' // use DynamicLoading; // A binary may or may not exist at this path. const path = './TestBinary'; // If loading fails an error will be issued and the 'try!' will halt. const bin = try! binary.load(path); And a procedure named ``foo`` with type ``proc(): void`` can be retrieved: .. code-block::chapel // Declare the type of the procedure. type P = proc(): void; // Retrieve a procedure named 'foo' from 'bin' with the type 'P'. const p1 = try! bin.retrieve('foo', P); // Call the procedure. p1(); When a procedure is retrieved from a loaded binary, the returned procedure value is callable on any locale despite :proc:`binary.retrieve()` only being called on a single locale. The returned procedure is considered to be ``extern`` and this is reflected in its type. .. note:: Currently, only procedures can be retrieved from loaded binaries. Support for retrieving references to data stored in a binary could be added in the future. .. record:: binary A wrapper around a dynamically loaded binary. .. method:: proc init=(rhs: binary) The initialized binary refers to the same binary stored in ``rhs``. .. method:: proc deinit() .. method:: operator = (ref lhs: binary, rhs: binary) After assignment, ``lhs`` will refer to the same binary stored in ``rhs``. .. method:: proc type load(path: string) throws Create a record representing a dynamically loaded binary using a string that stores the path to a binary file. The file may be any executable binary, though a "shared library" or "dynamic library" is by far the most common and well supported. The implementation will attempt to load a binary on all locales. If loading should fail on any locale then the entire process will be aborted and an error will be thrown. Dynamic loading can fail for a variety of reasons. It can fail if the binary could not be loaded on any locale. It can fail if no file was found at ``path`` or if a file was found but it did not have a suitable representation (e.g., the file format was not natively executable, or it was not marked as executable). :arg path: The path to the binary file to dynamically load :type path: `string` :throws DynLoadError: if dynamic loading fails .. method:: proc retrieve(name: string, type t) throws where isProcedureType(t) Fetch a procedure from a dynamically loaded binary. Throws an error if no procedure could be found. .. warning:: The procedure type ``t`` provided when calling :proc:`binary.retrieve()` is used verbatim and is not checked against the type of the underlying symbol in any way. If the type provided does not match the actual type of the underlying procedure, then the resulting behavior when the retrieved procedure is called is undefined. Crashes or other bugs could occur. The retrieved procedure is considered to be ``extern`` and will use an extern calling convention, the same as is used for other ``extern`` procedures declared in Chapel code. This impacts how it can be used. For example, it cannot currently be assigned to a procedure value that is not also considered ``extern``. :arg name: The name of the procedure to retrieve :type name: `string` :arg t: The type of the retrieved procedure :throws DynLoadError: if procedure lookup fails