Spec-Zone.ru › Octave 8

A.1.9 Вызов внешнего кода из файлов Oct

Связывание внешнего кода C с Octave относительно просто, так как функции C можно легко вызывать напрямую из C++. Возможная проблема заключается в том, что объявления внешних функций C могут потребоваться явно определить как функции C для компилятора. Если объявления внешних функций C находятся в заголовке foo.h, то тактика обеспечения того, что компилятор C++ будет обрабатывать эти объявления как код C, выглядит следующим образом:

#ifdef __cplusplus
extern "C"
{
#endif
#include "foo.h"
#ifdef __cplusplus
}  /* end extern "C" */
#endif

Вызов кода Fortran, однако, может вызвать больше трудностей. Это связано с различиями в том, как компиляторы обрабатывают связывание кода Fortran с кодом C или C++. Octave предоставляет несколько макросов, обеспечивающих согласованное поведение в нескольких компиляторах.

Внутренний код Fortran должен использовать функцию XSTOPX для замены функции Fortran STOP. XSTOPX использует обработчик исключений Octave для явного обработки случаев сбоя в коде Fortran. Обратите внимание, что Octave предоставляет свою собственную замену функции BLAS XERBLA, которая использует XSTOPX.

Если код вызывает XSTOPX, то для вызова базовой функции Fortran должен использоваться макрос F77_XFCN. Затем состояние исключения Fortran можно проверить с помощью глобальной переменной f77_exception_encountered. Если XSTOPX не будет вызываться, то вместо этого следует использовать макрос F77_FCN для вызова кода Fortran.

Использование F77_XFCN во всех случаях не наносит большого вреда, за исключением того, что для кода Fortran, который кратковременно выполняется и выполняется большое количество раз, потенциально существует накладные расходы. Однако если F77_FCN используется с кодом, который вызывает XSTOP, Octave может генерировать ошибку сегментации.

Пример включения функции Fortran в файл oct приведён в следующем примере, где C++-обёртка является

#include <octave/oct.h>
#include <octave/f77-fcn.h>

extern "C"
{
  F77_RET_T
  F77_FUNC (fortransub, FORTSUB)
    (const F77_INT&, F77_DBLE*, F77_CHAR_ARG_DECL F77_CHAR_ARG_LEN_DECL);
}

DEFUN_DLD (fortrandemo, args, , "Fortran Demo")
{
  if (args.length () != 1)
    print_usage ();

  NDArray a = args(0).array_value ();

  double *av = a.fortran_vec ();
  octave_idx_type na = a.numel ();

  OCTAVE_LOCAL_BUFFER (char, ctmp, 128);

  F77_XFCN (fortransub, FORTSUB,
            (na, av, ctmp F77_CHAR_ARG_LEN (128)));

  return ovl (a, std::string (ctmp));
}

а функция Fortran —

subroutine fortransub (n, a, s)
      implicit none
      character*(*) s
      real*8 a(*)
      integer*4 i, n, ioerr
      do i = 1, n
        if (a(i) .eq. 0d0) then
          call xstopx ('fortransub: divide by zero')
        else
          a(i) = 1d0 / a(i)
        endif
      enddo
      write (unit = s, fmt = '(a,i3,a,a)', iostat = ioerr)
     $       'There are ', n,
     $       ' values in the input vector', char(0)
      if (ioerr .ne. 0) then
        call xstopx ('fortransub: error writing string')
      endif
      return
      end

Этот пример демонстрирует большинство необходимых функций для связи с внешней функцией Fortran, включая передачу массивов и строк, а также обработку исключений. Для работы примера необходимо скомпилировать как файлы Fortran, так и C++.

mkoctfile fortrandemo.cc fortransub.f
[b, s] = fortrandemo (1:3)
⇒
  b = 1.00000   0.50000   0.33333
  s = There are   3 values in the input vector
[b, s] = fortrandemo (0:3)
error: fortrandemo: fortransub: divide by zero

© 1996–2023 The Octave Project Developers
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
https://docs.octave.org/v8.1.0/Calling-External-Code-from-Oct_002dFiles.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API