Spec-Zone.ru › Octave 9

Далее: Выделение локальной памяти в Oct-файлах, Предыдущее: Вызов функций Octave из Oct-файлов, Вверх: Oct-файлы [Содержание][Индекс]

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 регистронезависимы, а в зависимости от используемого компилятора Fortran, имена функций экспортируются либо с использованием строчных букв, либо с использованием заглавных букв. Кроме того, некоторые компиляторы добавляют ноль, одну или две подчеркивания "_" в конце имён экспортируемых функций. Это называется "переименованием имён".

Octave предоставляет макросы, которые позволяют писать код, автоматически обрабатывающий переименование имён для ряда различных компиляторов Fortran. Эти макросы F77_FUNC и F77_FUNC_. Первый следует использовать для функций Fortran, не содержащих подчеркиваний в имени. Последний следует использовать для функций Fortran с подчеркиваниями в имени. Оба макроса принимают два аргумента: первый — имя функции Fortran в нижнем регистре, второй — то же имя функции Fortran в верхнем регистре.

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

Обратите внимание, что мы не пытаемся обрабатывать функции Fortran, мы всегда используем оболочки подпрограмм для них и передаём значение возврата в качестве дополнительного аргумента.

Используйте следующие макросы для передачи строковых данных из C в Fortran:

F77_CHAR_ARG(x)
  F77_CONST_CHAR_ARG(x)
  F77_CXX_STRING_ARG(x)
  F77_CHAR_ARG_LEN(l)
  F77_CHAR_ARG_DECL
  F77_CONST_CHAR_ARG_DECL
  F77_CHAR_ARG_LEN_DECL

Используйте следующие макросы для написания функций на языке C, которые принимают строки в стиле Fortran:

F77_CHAR_ARG_DEF(s, len)
  F77_CONST_CHAR_ARG_DEF(s, len)
  F77_CHAR_ARG_LEN_DEF(len)
  F77_CHAR_ARG_USE(s)
  F77_CHAR_ARG_LEN_USE(s, len)

Используйте следующие макросы для типов Fortran в коде C++:

F77_INT4

Эквивалентно типу Fortran INTEGER*4

F77_DBLE

Эквивалентно типу Fortran DOUBLE PRECISION

F77_REAL

Эквивалентно типу Fortran REAL

F77_CMPLX

Эквивалентно типу Fortran COMPLEX

F77_DBLE_CMPLX

Эквивалентно типу Fortran DOUBLE COMPLEX

F77_LOGICAL

Эквивалентно типу Fortran LOGICAL

F77_RET_T

Тип возврата функции C++, которая действует как подпрограмма Fortran.

Используйте следующие макросы для возвращения из функций на языке C, которые должны действовать как подпрограммы Fortran. F77_NORETURN предназначен для использования в качестве последнего оператора такой функции, которая помечена атрибутом "noreturn".

F77_RETURN(retval)
  F77_NORETURN(retval)

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

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

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

extern "C"
{
  F77_RET_T
  F77_FUNC (fortransub, FORTRANSUB)
    (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_FUNC (fortransub, FORTRANSUB)
            (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

Далее: Выделение локальной памяти в Oct-файлах, Предыдущее: Вызов функций Octave из Oct-файлов, Вверх: Oct-файлы [Содержание][Индекс]

© 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/v9.2.0/Calling-External-Code-from-Oct_002dFiles.html

Spec-Zone.ru

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