### 13.8 Dynamically Linked Functions

On some systems, Octave can dynamically load and execute functions written in C++. Octave can only directly call functions written in C++, but you can also load functions written in other languages by calling them from a simple wrapper function written in C++.

Here is an example of how to write a C++ function that Octave can load, with commentary. The source for this function is included in the source distributions of Octave, in the file `examples/oregonator.cc`. It defines the same set of differential equations that are used in the example problem of Ordinary Differential Equations. By running that example and this one, we can compare the execution times to see what sort of increase in speed you can expect by using dynamically linked functions.

The function defined in `oregonator.cc` contains just 8 statements, and is not much different than the code defined in the corresponding M-file (also distributed with Octave in the file `examples/oregonator.m`).

Here is the complete text of `oregonator.cc`:

just

         #include <octave/oct.h>

         DEFUN_DLD (oregonator, args, ,
           "The `oregonator'.")
         {
           ColumnVector dx (3);

           ColumnVector x (args(0).vector_value ());

           dx(0) = 77.27 * (x(1) - x(0)*x(1) + x(0)
                            - 8.375e-06*pow (x(0), 2));

           dx(1) = (x(2) - x(0)*x(1) - x(1)) / 77.27;

           dx(2) = 0.161*(x(0) - x(2));

           return octave_value (dx);
         }

The first line of the file,

         #include <octave/oct.h>

includes declarations for all of Octave's internal functions that you will need. If you need other functions from the standard C++ or C libraries, you can include the necessary headers here.

The next two lines

         DEFUN_DLD (oregonator, args, ,
           "The `oregonator'.")

declares the function. The macro `DEFUN_DLD` and the macros that it depends on are defined in the files `defun-dld.h`, `defun.h`, and `defun-int.h` (these files are included in the header file `octave/oct.h`).

Note that the third parameter to `DEFUN_DLD` (`nargout`) is not used, so it is omitted from the list of arguments in order to avoid the warning from gcc about an unused function parameter.

The next line,

         ColumnVector dx (3);

simply declares an object to store the right hand sides of the differential equation, and the statement

         ColumnVector x (args(0).vector_value ());

extracts a vector from the first input argument. The `vector_value` method is used so that the user of the function can pass either a row or column vector. The `ColumnVector` constructor is needed because the ODE class requires a column vector. The variable `args` is passed to functions defined with `DEFUN_DLD` as an `octave_value_list` object, which includes methods for getting the length of the list and extracting individual elements.

In this example, we don't check for errors, but that is not difficult. All of the Octave's built-in functions do some form of checking on their arguments, so you can check the source code for those functions for examples of various strategies for verifying that the correct number and types of arguments have been supplied.

The next statements

         dx(0) = 77.27 * (x(1) - x(0)*x(1) + x(0)
                          - 8.375e-06*pow (x(0), 2));

         dx(1) = (x(2) - x(0)*x(1) - x(1)) / 77.27;

         dx(2) = 0.161*(x(0) - x(2));

define the right-hand side of the differential equation. Finally, we can return `dx`:

         return octave_value (dx);

The actual return type is `octave_value_list`, but it is only necessary to convert the return type to an `octave_value` because there is a default constructor that can automatically create an object of that type from an `octave_value` object, so we can just use that instead.

To use this file, your version of Octave must support dynamic linking. To find out if it does, type the command `octave_config_info ("dld")` at the Octave prompt. Support for dynamic linking is included if this command returns 1.

To compile the example file, type the command ``mkoctfile oregonator.cc`' at the shell prompt. The script `mkoctfile` should have been installed along with Octave. Running it will create a file called `oregonator.oct` that can be loaded by Octave. To test the `oregonator.oct` file, start Octave and type the command

         oregonator ([1, 2, 3], 0)

at the Octave prompt. Octave should respond by printing

         ans =

            77.269353
            -0.012942
            -0.322000

You can now use the `oregonator.oct` file just as you would the `oregonator.m` file to solve the set of differential equations.

On a 133 MHz Pentium running Linux, Octave can solve the problem shown in Ordinary Differential Equations, in about 1.4 seconds using the dynamically linked function, compared to about 19 seconds using the M-file. Similar decreases in execution time can be expected for other functions, particularly those that rely on functions like `lsode` that require user-supplied functions.

Just as for M-files, Octave will automatically reload a dynamically linked function when the file that defines it is more recent than the last time that the function was loaded. If more than one function is defined in a single `.oct` file, reloading the file may force other functions to be cleared and reloaded. If all the functions loaded from a given `.oct` file are cleared, Octave will automatically unload the `.oct` file.

— Built-in Variable: warn_reload_forces_clear

> If several functions have been loaded from the same file, Octave must clear all the functions before any one of them can be reloaded. If `warn_reload_forces_clear`, Octave will warn you when this happens, and print a list of the additional functions that it is forced to clear.

— Built-in Variable: variables_can_hide_functions

> If the value of this variable is nonzero, assignments to variables may hide previously defined functions of the same name. A negative value will cause Octave to print a warning, but allow the operation.

Additional examples for writing dynamically linked functions are available in the files in the `src` directory of the Octave distribution. Currently, this includes the files

         balance.cc   fft2.cc      inv.cc       qzval.cc
         chol.cc      filter.cc    log.cc       schur.cc
         colloc.cc    find.cc      lsode.cc     sort.cc
         dassl.cc     fsolve.cc    lu.cc        svd.cc
         det.cc       givens.cc    minmax.cc    syl.cc
         eig.cc       hess.cc      pinv.cc
         expm.cc      ifft.cc      qr.cc
         fft.cc       ifft2.cc     quad.cc

These files use the macro `DEFUN_DLD_BUILTIN` instead of `DEFUN_DLD`. The difference between these two macros is just that `DEFUN_DLD_BUILTIN` can define a built-in function that is not dynamically loaded if the operating system does not support dynamic linking. To define your own dynamically linked functions you should use `DEFUN_DLD`.

There is currently no detailed description of all the functions that you can call in a built-in function. For the time being, you will have to read the source code for Octave.