Fortran: Difference between revisions

Jump to navigation Jump to search
1,105 bytes added ,  13 July 2020
Add description about the data file.
(→‎C++ function: Update function to work with Octave 5.2.0+)
(Add description about the data file.)
 
(8 intermediate revisions by the same user not shown)
Line 1: Line 1:
This page describes an example of how to call liboctave functions from a Fortran program.
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,
In the example we will load a single matrix, stored in ASCII format, from a data file.
it consists of two steps:
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 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
# write Fortran code using the "iso_c_binding" intrinsic module to call the C++ function
 
=== Data file ===
 
{{File|data.txt|<syntaxhighlight lang="text">
1.59797350e-01 5.41307474e-01 1.12127655e-01 2.09249248e-01
3.22564589e-01 7.94307947e-01 8.25924316e-01 5.38352076e-01
3.63990736e-01 1.90371212e-02 2.89370865e-01 1.30131246e-01
6.28360462e-01 1.98831330e-01 6.89539723e-01 6.91062597e-01
</syntaxhighlight>}}
 
The file was generated with
 
<syntaxhighlight lang="octave">
A = rand (4);
save -ascii data.txt A
</syntaxhighlight>


=== C++ function ===
=== C++ function ===


{{Code|octave_file_io.cc: C++ function to load a matrix from an ASCII file in Octave native format|<syntaxhighlight lang="CC">
C++ function to load a single matrix, stored in ASCII format, from a data file.
 
{{File|octave_file_io.cc|<syntaxhighlight lang="C++">
// Octave header
// Octave header
#include <octave/oct.h>
#include <octave/oct.h>
Line 51: Line 69:
=== Header file ===
=== Header file ===


{{Code|octave_file_io.h: header file with C interface to octave_file_io.cc|<syntaxhighlight lang="C" style="font-size:13px">
Header file with C interface to {{Path|octave_file_io.cc}}.
 
{{File|octave_file_io.h|<syntaxhighlight lang="C">
#ifndef OCTAVE_FILE_IO_H
#ifndef OCTAVE_FILE_IO_H
#define OCTAVE_FILE_IO_H
#define OCTAVE_FILE_IO_H
Line 59: Line 79:
#endif
#endif
    
    
   int octave_load (const char* filename, const char* varname, double** data, int* numel);
   int octave_load (const char* filename, double** data, int* numel);


#ifdef __cplusplus
#ifdef __cplusplus
Line 68: Line 88:
</syntaxhighlight>}}
</syntaxhighlight>}}


=== Fortran Code ===


=== 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.


{{Code|octave_file_io_example.f90|<syntaxhighlight lang="fortran" style="font-size:13px">
{{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


Line 109: Line 129:
</syntaxhighlight>}}
</syntaxhighlight>}}


=== Compiling the code ===
Generate {{Path|octave_file_io.o}} from {{Path|octave_file_io.cc}}.
mkoctfile -I. -c octave_file_io.cc


Generate {{Path|octave_file_io_example.exe}} from {{Path|octave_file_io_example.f90}} including {{Path|octave_file_io.o}}.


mkoctfile -I. --link-stand-alone octave_file_io_example.f90 octave_file_io.o -o octave_file_io_example.exe -lgfortran


=== Compiling the code ===
If you receive errors about missing libraries, make sure your <code>LD_LIBRARY_PATH</code> is set correctly to find all Octave libraries, e.g.
 
$ ldd ./octave_file_io_example.exe
...
        libgfortran.so.4 => /usr/lib64/libgfortran.so.4 (0x00007fe9eb62b000)
        liboctinterp.so.8 => not found
        liboctave.so.8 => not found
...
 
Then find {{Path|liboctinterp.so.8}} and {{Path|liboctave.so.8}} on your system and type
 
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/lib/octave/{{Release}}/


  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


[[Category:Examples]]
[[Category:Examples]]

Navigation menu