Interfacing with other languages
- OctaveServer (using octave over the internet)
- OctaveEmbedded (including the octave interpreter in your program)
- OctaveEngine (calling octave from a separate program)
- OctaveTcl
- OctavePerl
- OctaveJava
- OctaveFortran
- OctaveFortranMex
- OctaveOcamlMex
Extending Octave
Octave has good support for interfacing with Fortran/C/C++. The examples subdirectory shows how to add a new function and a new type. There are many more examples in the src/DLD-FUNCTIONS directory as well as in OctaveForge.
Christoph Spiel has written DaCodaAlFine which is also a good introduction, though it is a little out of date.
FIXME Extend DaCodaAlFine with information about OCTAVE_QUIT (a macro you need in your loops to handle Ctrl-C), OCTAVE_LOCAL_BUFFER (a macro to define a temporary buffer which is cleaned when you leave the scope), how to define/set/get global/local/builtin variables and so on.
Paul Thomas has written [Dal Segno al Coda] which extends the DaCodaAlFine for users who aren't experienced in C++.
The CPPQuickReference is a brief summary of matrix operations in Octave and their equivalents in C++ using the Octave libraries. It might make sense in the future to merge this with the wikified Da Coda al Fine document.
There is also a partial support for the mex interface[1] in OctaveForge. This is potentially a great thing to have to help people out of Matlab license hell and get them involved in free software. Ask on the mailing list for advice on filling in the missing functions. The interface is slower than it needs to be because it makes unnecessary copies of the data, but this cost can be reduced with some effort. Complex data has a different internal representation, so extra costs can't be completely eliminated without modifying your code in octave-specific ways. The native Octave inteface is simple to use, so you may want to consider recoding.
Using gdb to debug your extensions
gdb can be used to debug DEFUN_DLD functions. There are N preliminary steps one should during the compilations phase.
- compile all of the code with -g or -ggdb
- compile all the code that you want to step through and examine variables in with -O0
- make sure that the linker is not stripping symbol names
With that done, it the shared objects (.oct files) should be ready to go. The debugger can simply be started with 'gdb octave' assuming it is in your path. However, the DEFUN_DLD has not been loaded and therefore gdb cannot set any of the break points or examine it at all. The following steps are not the only solution, but I find them to be effective:
- start debugging with 'gdb octave' or whatever the correct command is for your environment
- 'run' octave
- after the octave prompt appears, display the help for your dynamic function. That is, if your function is called 'myfunc.oct', call 'help myfunc'. This will load your dynamic funtion into octave space and gdb without tickling the bug
- ctrl-c will then return you to the gdb prompt
- set break points inside of your DEFUN_DLD and have fun
If you find that gdb is not pointing to the line that is being executed or the that the flow of the program is not as expected, then make sure you used the -O0 switch. Octave normally uses the -O2 switch which optimizes the code making it less inituitive for debugging.
Calling GNU Octave functions/m-files from C++
This documentation is attributed heavily to Arjan Vermeij who first raised and explained the issue.
Let us assume that one has an m-file, i.e. the GNU Octave function: exampleOctaveFunction.m
function [resultScalar, resultString, resultMatrix] = exampleOctaveFunction (inScalar, inString, inMatrix)
resultScalar = (inScalar * pi);
resultString = strcat ('Good morning Mr. ', inString);
resultMatrix = (inMatrix + 1);
endfunction
The question now is, how does one call the above function from within C++, e.g. from how-to-call-octave.cpp
The easiest way is via feval but one needs to not forget to terminate the octave interpreter via do_octave_atexit ()
#include <octave/oct.h>
#include <octave/octave.h>
#include <octave/parse.h>
#include <octave/toplev.h> /* do_octave_atexit */
int main (const int argc, char ** argv)
{
const char * argvv [] = {"" /* name of program, not relevant */, "--silent"};
octave_main (2, (char **) argvv, true /* embedded */);
octave_value_list functionArguments;
functionArguments (0) = 2;
functionArguments (1) = "D. Humble";
Matrix inMatrix (2, 3);
inMatrix (0, 0) = 10;
inMatrix (0, 1) = 9;
inMatrix (0, 2) = 8;
inMatrix (1, 0) = 7;
inMatrix (1, 1) = 6;
functionArguments (2) = inMatrix;
const octave_value_list result = feval ("exampleOctaveFunction", functionArguments, 1);
std::cout << "resultScalar is " << result (0).scalar_value () << std::endl;
std::cout << "resultString is " << result (1).string_value () << std::endl;
std::cout << "resultMatrix is\n" << result (2).matrix_value ();
do_octave_atexit ();
}
If you have a Linux machine the following Makefile will perform the building process for you; beware that your directories may be different and you will need to change them accordingly:
OCTAVE_INCLUDE_DIR=/usr/include/octave-3.0.1/
OCTAVE_LIB_DIR=/usr/lib/octave-3.0.1/
makefile:
all: octcall
clean:
-rm octcall.o octcall
octcall: octcall.o
g++ -L$(OCTAVE_LIB_DIR) -l octinterp -o octcall octcall.o
octcall.o: how-to-call-octave.cpp
g++ -c -I$(OCTAVE_INCLUDE_DIR) -I$(OCTAVE_INCLUDE_DIR)octave -o octcall.o how-to-call-octave.cpp
Examples of Extending Octave
CategoryCode