Difference between revisions of "Fortran"

From Octave
Jump to navigation Jump to search
(→‎Header file: Update.)
(→‎Fortran Code: Update Fortran code.)
Line 74: Line 74:
 
=== Fortran Code ===
 
=== Fortran Code ===
  
{{Code|octave_file_io_example.f90|<syntaxhighlight lang="fortran" style="font-size:13px">
+
Fortran main program to read the plain ASCII matrix with the help of the Octave-C++ function.  The read in matrix is printed to the screen.
 +
 
 +
{{File|octave_file_io_example.f90|<syntaxhighlight lang="fortran">
 
program octave_file_io_example
 
program octave_file_io_example
 
+
 
 
   use iso_c_binding
 
   use iso_c_binding
   
+
 
 
   implicit none
 
   implicit none
  
   interface  
+
   interface
     function octave_load (filename, varname, data, numel) bind(c, name="octave_load")
+
     function octave_load (filename, data, numel) bind(c, name="octave_load")
     
+
 
 
       use iso_c_binding
 
       use iso_c_binding
 
       implicit none
 
       implicit none
  
 
       integer(c_int) :: octave_load
 
       integer(c_int) :: octave_load
     
+
 
 
       character(kind=c_char), intent(in) :: filename(*)
 
       character(kind=c_char), intent(in) :: filename(*)
      character(kind=c_char), intent(in) :: varname(*)
+
 
     
 
 
       type(c_ptr), intent(out) :: data
 
       type(c_ptr), intent(out) :: data
 
       integer(c_int), intent(out) :: numel
 
       integer(c_int), intent(out) :: numel
     
+
 
 
     end function octave_load
 
     end function octave_load
 
   end interface
 
   end interface
 
+
 
   integer(c_int) :: res  
+
   integer(c_int) :: res
 
   type(c_ptr) :: data
 
   type(c_ptr) :: data
 
   real(c_double), pointer :: fdata(:)
 
   real(c_double), pointer :: fdata(:)
 
   integer(c_int) :: numel
 
   integer(c_int) :: numel
  
   res = octave_load (c_char_'pippo.octxt' // c_null_char, c_char_'A' // c_null_char, data, numel)
+
   res = octave_load (c_char_'data.txt' // c_null_char, data, numel)
 
+
 
 
   call c_f_pointer (data, fdata, (/numel/))
 
   call c_f_pointer (data, fdata, (/numel/))
 
+
 
 
   write (*,*) fdata
 
   write (*,*) fdata
  
 
end program octave_file_io_example
 
end program octave_file_io_example
 
</syntaxhighlight>}}
 
</syntaxhighlight>}}
 
 
 
  
 
=== Compiling the code ===
 
=== Compiling the code ===

Revision as of 22:02, 12 July 2020

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

C++ function to load a single matrix, stored in ASCII format, from a data file.

File: octave_file_io.cc
// Octave header
#include <octave/oct.h>
#include <octave/ls-mat-ascii.h>

// Custom header containing the C compatible interface
#include <octave_file_io.h>

//! Load a single matrix, stored in ASCII format, from a data file.
//!
//! @param file_name name of the data file.
//! @param data pointer to the read-in matrix stored as fortran vector
//!             (column-major order).
//! @param numel number of elements in @p data.

int octave_load (const char* file_name, double** data, int* numel)
{
  // Define variable to hold the read data.
  octave_value read_data;

  // Read a plain ASCII matrix from data file.
  std::ifstream in_file_stream (file_name, std::ios::binary);
  read_mat_ascii_data (in_file_stream, file_name, read_data);
  in_file_stream.close ();

  // Convert read data to numerical array (matrix).
  NDArray A = read_data.array_value ();

  // Extract number of elements in matrix A.
  *numel = A.numel ();

  // Allocate memory to pointer to returned values.
  *data  = (double*) malloc (A.numel () * sizeof (double));

  // Copy the content of matrix A to data structure Fortran can handle.
  memcpy (*data, A.fortran_vec (), A.numel () * sizeof (double));

  return 0;
}

Header file

Header file with C interface to octave_file_io.cc.

File: octave_file_io.h
#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

Fortran main program to read the plain ASCII matrix with the help of the Octave-C++ function. The read in matrix is printed to the screen.

File: octave_file_io_example.f90
program octave_file_io_example

  use iso_c_binding

  implicit none

  interface
     function octave_load (filename, 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(*)

       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_'data.txt' // 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