Latest revision |
Your text |
Line 1: |
Line 1: |
| This page describes an example of how to call liboctave functions from a Fortran program.
| |
| In the example we will load a single matrix, stored in ASCII format, from a data file.
| |
| 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
| |
|
| |
|
| === Data file ===
| | {{Code|C++ function to load a matrix from an ASCII file in Octave native format|<syntaxhighlight lang="C" style="font-size:13px"> |
| | | #include <octave_file_io.h> |
| {{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 to load a single matrix, stored in ASCII format, from a data file.
| |
|
| |
| {{File|octave_file_io.cc|<syntaxhighlight lang="C++">
| |
| // Octave header
| |
| #include <octave/oct.h> | | #include <octave/oct.h> |
| #include <octave/ls-mat-ascii.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> |
|
| |
|
| // Custom header containing the C compatible interface
| | int octave_load (const char* filename, const char* varname, double** data, int* numel) |
| #include <octave_file_io.h>
| | { |
| | |
| | string_vector argv (1); |
| | load_save_format format = LS_ASCII; |
|
| |
|
| //! Load a single matrix, stored in ASCII format, from a data file.
| | install_types (); |
| //!
| | argv(0) = varname; |
| //! @param file_name name of the data file.
| | |
| //! @param data pointer to the read-in matrix stored as fortran vector
| | std::ios::openmode mode = std::ios::in | std::ios::binary; |
| //! (column-major order).
| | std::string fname (filename); |
| //! @param numel number of elements in @p data.
| |
|
| |
|
| int octave_load (const char* file_name, double** data, int* numel)
| | std::ifstream file (fname.c_str (), mode); |
| {
| | |
| // Define variable to hold the read data. | | octave_scalar_map m = do_load (file, fname, format, oct_mach_info::flt_fmt_unknown, |
| octave_value read_data;
| | false, false, true, argv, 0, 1, 1).scalar_map_value (); |
|
| |
|
| // Read a plain ASCII matrix from data file. | | file.close (); |
| 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). | | Array<double> M = m.contents (varname).array_value (); |
| NDArray A = read_data.array_value (); | | if (error_state) |
| | return -1; |
|
| |
|
| // Extract number of elements in matrix A. | | *data = (double*) malloc (M.numel () * sizeof (double)); |
| *numel = A.numel (); | | *numel = M.numel (); |
|
| |
|
| // Allocate memory to pointer to returned values. | | memcpy (*data, M.fortran_vec (), *numel * sizeof (double)); |
| *data = (double*) malloc (A.numel () * sizeof (double));
| |
|
| |
|
| // Copy the content of matrix A to data structure Fortran can handle.
| | return 0; |
| memcpy (*data, A.fortran_vec (), A.numel () * sizeof (double));
| |
| | |
| return 0; | |
| } | | } |
| </syntaxhighlight>}} | | </syntaxhighlight>}} |
|
| |
|
| === Header file ===
| |
|
| |
|
| Header file with C interface to {{Path|octave_file_io.cc}}.
| | {{Code|C interface to a function linking to liboctave|<syntaxhighlight lang="C" style="font-size:13px"> |
| | |
| {{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 79: |
Line 57: |
| #endif | | #endif |
| | | |
| int octave_load (const char* filename, double** data, int* numel); | | int octave_load (const char* filename, const char* varname, double** data, int* numel); |
|
| |
|
| #ifdef __cplusplus | | #ifdef __cplusplus |
Line 87: |
Line 65: |
| #endif | | #endif |
| </syntaxhighlight>}} | | </syntaxhighlight>}} |
|
| |
| === 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|<syntaxhighlight lang="fortran">
| |
| 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
| |
| </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
| |
|
| |
| 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}}/
| |
|
| |
|
| |
| [[Category:Examples]]
| |