- publishing free software manuals
GNU Octave Manual
by John W. Eaton
Paperback (6"x9"), 324 pages, 4 figures
ISBN 0954161726
RRP £19.99 ($29.99)

Get a printed copy>>>

11.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 section 20.1 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’:

#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 to in order to avoid the warning from gcc about an unused function parameter.

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 column vector from the input arguments. 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

ColumnVector dx (3);

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 section 20.1 Ordinary Differential Equations in about 1.4 second 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 dynamically linked functions when the files that define them are more recent than the last time that the function was loaded. Two variables are available to control how Octave behaves when dynamically linked functions are cleared or reloaded.

Built-in Variable: auto_unload_dot_oct_files
If the value of auto_unload_dot_oct_files is nonzero, Octave will automatically unload any ‘.oct’ files when there are no longer any functions in the symbol table that reference them.

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.

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.

ISBN 0954161726GNU Octave ManualSee the print edition