Fortran

From Octave
Revision as of 21:21, 29 November 2012 by Cdf (talk | contribs) (Example of writing F2003 Code linking to Octave)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

This page describes an example of how to call liboctave functions from a Fortran program. In the example we will load an Octave array from a file in Octave's native ASCII format, it consists of two steps:

- write a C++ function with a C compatible interface and C linkage that reads a variable from an Octave ASCII file
- write Fortran code using the "iso_c_binding" intrinsic module to call the C++ function

C++ function

Code: octave_file_io.cc: C++ function to load a matrix from an ASCII file in Octave native format
#include <octave_file_io.h>


#include <octave/oct.h>
#include <octave/ov.h>
#include <fstream>
#include <ls-oct-ascii.h>
#include <octave/octave.h>
#include <octave/parse.h>
#include <octave/toplev.h>
#include <octave/load-save.h>
#include <octave/oct-map.h>
#include <cstring>

int octave_load (const char* filename, const char* varname, double** data, int* numel)
{
  
  string_vector argv (1);
  load_save_format format = LS_ASCII;

  install_types ();  
  argv(0) = varname;
  
  std::ios::openmode mode = std::ios::in | std::ios::binary;
  std::string fname (filename);

  std::ifstream file (fname.c_str (), mode);
  
  octave_scalar_map m = do_load (file, fname, format, oct_mach_info::flt_fmt_unknown,
                                 false, false, true, argv, 0, 1, 1).scalar_map_value ();

  file.close ();  

  Array<double> M = m.contents (varname).array_value ();
  if (error_state)
    return -1;

  *data = (double*) malloc (M.numel () * sizeof (double));
  *numel = M.numel ();

  memcpy (*data, M.fortran_vec (), *numel * sizeof (double));

  return 0;  
}


Header file

Code: octave_file_io.h: header file with C interface to octave_file_io.cc
#ifndef OCTAVE_FILE_IO_H
#define OCTAVE_FILE_IO_H

#ifdef __cplusplus
extern "C" {
#endif
  
  int octave_load (const char* filename, const char* varname, double** data, int* numel);

#ifdef __cplusplus
}
#endif

#endif


Fortran Code

Code: octave_file_io.cc: C++ function to load a matrix from an ASCII file in Octave native format
program octave_file_io_example
  
  use iso_c_binding
    
  implicit none

  interface 
     function octave_load (filename, varname, data, numel) bind(c, name="octave_load")
       
       use iso_c_binding
       implicit none

       integer(c_int) :: octave_load
       
       character(kind=c_char), intent(in) :: filename(*)
       character(kind=c_char), intent(in) :: varname(*)
       
       type(c_ptr), intent(out) :: data
       integer(c_int), intent(out) :: numel
       
     end function octave_load
  end interface
  
  integer(c_int) :: res 
  type(c_ptr) :: data
  real(c_double), pointer :: fdata(:)
  integer(c_int) :: numel

  res = octave_load (c_char_'pippo.octxt' // c_null_char, c_char_'A' // c_null_char, data, numel)
  
  call c_f_pointer (data, fdata, (/numel/))
  
  write (*,*) fdata

end program octave_file_io_example



Compiling the code

 mkoctfile -I. octave_file_io.cc 
 mkoctfile -I. --mkoctfile --link-stand-alone octave_file_io_example.f90 octave_file_io.o -o octave_file_io_example