Интерфейс между FORTRAN и C

Илюшкин Б. И., Козачек В. В.



1 Общее описание

При организации межязыкового интерфейса программных модулей необходимо учитывать особенности соглашений о внешних именах, типах данных, передаваемых параметрах, принятые в каждом из компиляторов.

Соглашения о внешних именах

Перед помещением внешнего имени (глобальная переменная, функция, подпрограмма и т.д.) в объектный файл, компиляторы осуществляют следующие действия:

                          CONVEX FORTRAN

       _name_

        _MAIN__

        __name_

где name - имя COMMON блока;

        ___blnk_

                          CONVEX C

        _name

  extern void f_ (  )

  extern  g_ (   )

Пример 1.1 Вызов модуля FORTRAN из C.

#include < stdio.h> 
extern void sub1_( );
 main()
{
 . . . . . . . . . . . . . . . . . . . . .  Source file is   exc.c
 sub1_(  ) ;
 . . . . . . . . . . . . . . . . . . . . .
}

            SUBROUTINE SUB1(  )
 . . . . . . . . . . . . . . . . . . . . .
 . . . . . . . . . . . . . . . . . . . . .  Source file is   exf.f
 . . . . . . . . . . . . . . . . . . . . .
            RETURN
            END

Командная строка запуска компилятора

        fc -c  exf.f
        cc  exc.c  exf.o

Примечание.

В головном модуле exc.c добавляется символ ('_') в конце внешнего имени вызываемого FORTRAN модуля sub1,т.к. компилятор C добавляет символ ('_') в начале имени.

При компиляции исходного FORTRAN модуля SUB1 компилятор FORTRAN добавляет символ ('_') в начало и конец имени.

Пример 1.2 Вызов модуля C из FORTRAN.

            PROGRAM MAIN                    Source file is   exf.f
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
            COMMON A
            COMMON /NAMED/ X
            CALL SUB1(  )
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
            END

   struct block { double a ; int b ; } ;

   void sub1_(  )                           Source file is   exc.c
 {
  extern struct block __blnk_ ;
  extern struct block  _named_ ;
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
  __blnk_.a =   ;
  _named_.b =   ;
 }

Командная строка запуска компилятора

        cc -c  exc.c
        fc -sa exf.f  exc.o

Примечание.

В вызываемом модуле exc.c внешние имена именованного (_named_) и неименованного (__blnk_) COMMON блоков содержат на один символ ('_') впереди меньше по сравнению с соглашением об именах компилятора FORTRAN, т.к. компилятор C добавляет ('_') в начале имени. Аналогично и в отношении sub1_.

2 Соглашения о типах данных

Ниже приводится таблица соответствия типов данных CONVEX FORTRAN и CONVEX C. Типы данных разбиты на подклассы. При этом любой тип данных одного подкласса FORTRAN соответствует любому типу данных этого же подкласса C.

Таблица 1. Соответствие между типами данных FORTRAN и C.

------------------------------------------------------------------------
N |           FORTRAN                 |                    C
--|-----------------------------------|---------------------------------
1.|INTEGER*1   X                      | char x;
  |BYTE        X                      |
  |LOGICAL*1   X                      |
  |                                   |
2.|INTEGER*2   X                      | short x;
  |LOGICAL*2   X                      | short int x;
  |                                   |
3.|INTEGER     X                      | int x;
  |INTEGER*4   X                      | long x;
  |LOGICAL*4   X                      | long int x;
  |LOGICAL     X                      | enum x;
  |                                   |
4.|INTEGER*8   X                      | long long x;
  |LOGICAL*8   X                      | long long int x;
  |                                   |
5.|none                               | unsigned x;
  |                                   |
6.|REAL        X                      | float x;
  |REAL*4      X                      |
  |                                   |
7.|REAL*8      X                      | double x;
  |DOUBLE PRECISION   X               | long double x;
  |                                   | long float x;
  |                                   |
8.|REAL*16     X                      | none
  |                                   |
9.|COMPLEX     X                      | struct{float r,i;} x;
  |COMPLEX*8   X                      |
  |                                   |
10|COMPLEX*16  X                      | struct{double dr,di;} x;
  |DOUBLE COMPLEX  X                  |
  |                                   |
11|CHARACTER*6   X                    | char x[7];
  |                                   |
12|A(2,3)={ A(1,1),A(2,1),A(1,2),     | a[2][3]={a[0][0],a[0][1],
  |         A(2,2),A(1,3),A(2,3) }    | a[0][2],a[1][0],a[1][1],a[1][2]}
  |                                   |
13|COMMON /NAMED/ -- named            | struct block _named_;
  |                                   |
14|COMMON         -- unnamed          | struct block __blnk_;
  |                                   |
-----------------------------------------------------------------------

Примечание.

1. По умолчанию все типы подклассов 1-4 в языке C являются signed.

2. Типы long long, long long int, long float являются расширением ANSI C стандарта и могут быть использованы только с CONVEX C компилятором.

3. Размер текстового массива (строки) в C на единицу превышает количество символов (за счет добавления нулевого элемента).

4. Многомерные массивы в C размещаются по строкам, индексация начинается с 0. Многомерные массивы в FORTRAN размещаются по столбцам, индексация начинается с 1.

3 Соглашения о передаваемых параметрах

                          CONVEX  FORTRAN

Параметры вызываемой программы передаются через ссылку (адрес). Текстовые параметры передают дополнительный аргумент по значению (длину текстовой переменной), который добавляется в конце списка параметров. В случае нескольких текстовых параметров дополнительные аргументы добавляются для каждого из них и располагаются последовательно в конце списка параметров.

Пример 3.1

      COMPLEX*8 FUNCTION CMADD(J1,J2)
      INTEGER*4 J1,J2
      . . . . . . . . . . . . . . . .
      . . . . . . . . . . . . . . . .
Компилятор FORTRAN транслирует COMPLEX*8 функцию CMADD в подпрограмму CMADD, в которой первый аргумент является адресом возвращаемого функцией значения:

      SUBROUTINE CMADD(RET,J1,J2)
      INTEGER*4 RET
      INTEGER*4 J1,J2
      . . . . . . . . . . . . . .
      . . . . . . . . . . . . . .
      RET=%REF(X)

где X - возвращаемое значение.

Функции, возвращающие текстовое значение, добавляют два дополнительных аргумента (адрес текстовой переменной результата и максимальную длину текстовой переменной) перед первым параметром списка.

Пример 3.2

      CHARACTER*5 FUNCTION CADD(J1,J2)
      INTEGER J1,J2
      . . . . . . . . . . . . . . . . .
      . . . . . . . . . . . . . . . . .

Компилятор FORTRAN транслирует CHARACTER функцию CADD в программу CADD, в которой первым аргументом является адрес, а вторым длина текстовой переменной возвращаемого значения:

      SUBROUTINE CADD(RET,5,J1,J2)
      INTEGER*4 RET
      INTEGER*4 J1,J2
      . . . . . . . . . . . . . . .
      . . . . . . . . . . . . . . .
      RET=%REF(X)

где X - возвращаемое значение.

                          CONVEX  C

Параметры вызываемой программы передаются по значению,за исключением массивов, которые передаются через ссылку (адрес).

4 Встроенные функции и директивы компилятора CONVEX FORTRAN для согласования типов данных и передаваемых параметров

%VAL(arg) - осуществляет передачу параметра arg по значению;

%REF(arg) - осуществляет передачу параметра arg через ссылку.

Аргументами вышеприведенных функций могут быть только фактические параметры из списка вызываемого модуля.

%LOC(arg) - вычисляет адрес аргумента ;

ROW_WISE(arg) - изменяет порядок индексов двумерного массива (на обратный).

Таблица 2. Соответствия типов аргументов встроенных функций.

-----------------------------------------------------------------------
 Name      | Type of argument           | Examples
-----------|----------------------------|------------------------------
 %VAL      | LOGICAL(*1,2,4)            | CALL SUB(3,%VAL(10))
           | INTEGER(*1,2,4)            | first parameter passed by
           | REAL *4                    | reference,second by value.
           |                            |
 %REF      | excluding  Hollerith       |
           |                            |
 %LOC      | INTEGER                    | I=%LOC(J)-4
           | (index of array)           | adress of the word preceding J
           |                            |
 ROW_WISE  | name of array              | the description
           |                            |   DIMENSION A(4,10)
           |                            | is equivalent to :
           |                            |   C$DIR ROW_WISE (A)
           |                            |   DIMENSION A(10,4)
-----------------------------------------------------------------------

5 Примеры: вызов модулей FORTRAN из C

Передача и возврат целых и вещественных переменных

Пример 5.1

#include < stdio.h>                           /* Source file is cfir.c */
extern void sub1_( int *integer, float *real );
 main()
{
  int i = 0;
  float a = 0.0;
  sub1_(& i,& a);
  (void) printf ("%d\n%f\n", i, a );
}

      SUBROUTINE SUB1( J, B )                  ! Source file is cfir2.f
      INTEGER*4 J
      REAL*4 B
      J=1234567
      B = 9876.543
      RETURN
      END

Строка запуска компилятора

        fc -c cfir2.f
        cc cfir.c cfir2.o

Результат

        i= 1234567
        a= 9876.542969

Примечание.

При передаче переменных i, a используется операция взятия адреса & , поскольку в FORTRAN параметры передаются через ссылку. Соответственно в строке описания прототипа sub1_ в головной программе параметры описываются как указатели.

Пример 5.2

#include < stdio.h>                        /* Source file is cffunc.c */
extern float addem_(float *al, float *a2);
extern int iaddem_(int *i1,int *i2);
  main()
{
     int i1 = 43;
     int i2 = 12;
     float a1 = 43.;
     float a2 = 12.;
     (void)printf("%d\n",iaddem_(& i1,& i2) );
     (void)printf("%f\n", addem_(& a1, & a2) );
}

      INTEGER FUNCTION IADDEM ( J1,J2 )     ! Source file is cffunc2.f
      INTEGER J1, J2
      IADDEM = J1 + J2
      RETURN
      END
      REAL FUNCTION ADDEM(B1, B2)
      REAL B1, B2
      ADDEM = B1 + B2
      RETURN
      END

Строка запуска компилятора

        fc -c cffunc2.f
        cc cffunc.c cffunc2.o

Результат

        iadd= 55
        add= 55.000000

Примечание.

IADDEM( ), ADDEM( ) - FORTRAN функции, возвращающие сумму двух аргументов.

Передача и возврат текстовых переменных

Пример 5.3

#include < stdio.h>                        /* Source file is cfchar.c */
extern void sub1_( char str1[], char str2[], int *arg3,
		     long len1, long len2 );
main ()
{
   char str1[10];
   char str2[6];
   int num = 4;
   sub1_(str1,str2,& num,10,6);
   str1[9] = '\0';
   str2[5] = '\0';
   (void) printf ("%s %s\n",str1,str2);
}

      SUBROUTINE  SUB1 (CVAR1,CVAR2,CVAR3)  ! Source file is cfchar2.f
      CHARACTER*10 CVAR1
      CHARACTER*6 CVAR2
      INTEGER CVAR3
      CVAR1 = '123456789'
      CVAR2 = 'abcde'
      RETURN
      END

Строка запуска компилятора

        fc -c cfchar2.f
        cc cfchar.c cfchar2.o

Результат

        str1= 123456789
        str2= abcde

Примечание.

В строке описания прототипа sub1_ и в строке обращения содержатся два дополнительных параметра - длины переменных str1, str2, отсутствующие в списке формальных параметров SUB1.

Поскольку FORTRAN автоматически не добавляет символ '\0' в конце строки, необходимо это выполнить в головной программе перед вызовом функции печати printf.

Пример 5.4

#include < stdio.h>                       /* Source file is cfcfunc.c */
extern void makestr_(char cstring[], long int cstr_len, char *arg1,
                     int arg2, long int arg1_len );
main()
{
     char cstring[20];
     char wxyz[] = " wxyz";
     int arg = 60;
     makestr_(cstring, 20L,wxyz, arg, sizeof(wxyz) -1 );
     (void)printf("%s\n",cstring );
}

      CHARACTER*20 FUNCTION MAKESTR (CVAR1,ARG)
      CHARACTER*5 CVAR1
      INTEGER ARG                          ! Source file is cfcfunc2.f
      MAKESTR = CVAR1// ' edcba'//CHAR(0)
      RETURN
      END

Строка запуска компилятора

        fc -c cfcfunc2.f
        cc cfcfunc.c cfcfunc2.o -lf77

Результат

        cstring= wxyz edcba

Примечание.

Компилятор FORTRAN транслирует функцию MAKESTR в подпрограмму с именем makestr_, в которой первым аргументом является адрес, а вторым длина возвращаемого текстового значения. Последний аргумент - длина передаваемой текстовой переменной (без элемента '\0').

В MAKESTR используется встроенная функция for$s_cat для операции конкатенации, требующая библиотеки libf77. Поэтому при компоновке используется дополнительная опция -lf77.

Передача и возврат комплексных переменных и структур

Пример 5.5

#include < stdio.h>                       /* Source file is cfcmplx.c */
typedef struct{ float r,i;} complex8_t;
typedef struct{ double r,i;} complex16_t;
extern void sub1_( complex8_t *cx1, complex16_t *cx2);

main ( )
{
   complex8_t cx1;
   complex16_t cx2;
   sub1_ (& cx1, & cx2);
   (void)printf ("(%f,%f)\n",cx1.r,cx1.i);
   (void)printf ("(%f,%f)\n",cx2.r,cx2.i);
}

      SUBROUTINE SUB1 (CX1,CX2)             ! Source file is cfcmplx2.f
      COMPLEX*8 CX1
      COMPLEX*16 CX2
      CX1 = (1234.0,5678.0)
      CX2 = (8765.0,4321.0)
      RETURN
      END

Строка запуска компилятора

        fc -c cfcmplx2.f
        cc cfcmplx.c cfcmplx2.o

Результат

        cx1= (1234.000000,5678.000000)
        cx2= (8765.000000,4321.000000)

Пример 5.6

#include < stdio.h>                       /* Source file is cfxfunc.c */
typedef struct {float r, i;} complex8_t;
extern void makecx_( complex8_t *cx, float *a1, float *a2);
main()
{
    float a1 = 43.;
    float a2 = 12.;
    complex8_t cx;
    makecx_(& cx,& a1,& a2);
    (void)printf("(%f,%f)\n", cx.r, cx.i );
}

      COMPLEX FUNCTION MAKECX (B1, B2)      ! Source file is cfxfunc2.f
      REAL B1,B2
      MAKECX = CMPLX (B1*2, B2*2)
      RETURN
      END

Результат

        cx= (86.000000,24.000000)

Примечание.

В строке описания прототипа makecx_ и в строке обращения добавляется дополнительный аргумент (адрес результата) перед первым параметром списка.

Возвращаемое MAKECX значение является структурой. В данном примере используется механизм возврата значений, принятый по умолчанию компилятором C (через сегмент данных памяти).

Пример 5.7

В данном примере используется новый (стековый) механизм возврата значений. Строка запуска компилятора C включает дополнительную опцию

         cc -compat rrf=stack

Данная опция может применяться при компиляции функций С, у которых возвращаемый результат является структурой и передается по значению. Для использования нового механизма возврата значений необходимо ввести в исходный код программы cfxfunc.c изменения. Ниже приводятся модифицированные строки cfxfunc.c из примера 2, а также модифицированный исходный код.

 . . . . . . . . . . . . . . . . . . . . . . . . . .
 extern complex8_t makecx_(float*a1,float*a2);
 . . . . . . . . . . . . . . . . . . . . . . . . . .
 . . . . . . . . . . . . . . . . . . . . . . . . . .
 cx=makecx_(& a1,& a2);
 . . . . . . . . . . . . . . . . . . . . . . . . . .
 . . . . . . . . . . . . . . . . . . . . . . . . . .

#include < stdio.h>                      /* Source file is cfxfunc1.c */
typedef struct {float r, i;} complex8_t;
extern complex8_t makecx_(float*a1,float*a2);
main()
{
    float a1 = 43.;
    float a2 = 12.;
    complex8_t cx;
    cx=makecx_(& a1,& a2);
    (void)printf("(%f,%f)\n", cx.r, cx.i );
}

Строка запуска компилятора

        fc -c cfxfunc2.f
        cc -compat rrf=stack cfxfunc1.c cfxfunc2.o

Результат

        cx= (86.000000,24.000000)

Передача и возврат массивов переменных

Пример 5.8

#include < stdio.h>                        /* Source file is cfarr.c */
extern void sub1_( int a[][3] );
main ()
{
   int a[5] [3];
   int i;
   sub1_(a);
   for(i=0; i< 5; i++)
     (void)printf("%3d %3d %3d\n", a[i][0],a[i][1],a[i][2]);
}

      SUBROUTINE SUB1 (A)                   ! Source file is cfarr2a.f
C$DIR ROW_WISE (A)
      INTEGER A(5,3)
      DO I = 1,5
      DO J = 1,3
      A(I,J) = I*J
      ENDDO
      ENDDO
      RETURN
      END
      SUBROUTINE SUB1 (A)                   ! Source file is cfarr2b.f
      INTEGER A(3,5)
      DO J = 1, 5
         DO I = 1, 3
            A(I,J) = I*J
         ENDDO
      ENDDO
      RETURN
      END

Строка запуска компилятора

        fc -c cfarr2a.f
        fc -c cfarr2b.f
        cc cfarr.c cfarr2a.o

Результат

           1   2   3
           2   4   6
        a= 3   6   9
           4   8  12
           5  10  15

Примечание.

Для согласования разныж способов хранения и индексации массивов в FORTRAN и C ,исходный код FORTRAN программы модифицируется путем включения директивы компилятора ROW_WISE в модуле cfarr2a.f или посредством инверсии индексов массива в модуле cfarr2b.f.

6 Примеры: вызов модулей С из FORTRAN

Передача переменных через COMMON блок

Пример 6.1

                                            ! Source file is fccmn.f
      PROGRAM MAIN
      REAL*8 A, X
      INTEGER*4 B, Y
      COMMON A, B
      COMMON /NAMED/ X, Y
      CALL SUB1 ( )
      PRINT *, A, B
      PRINT *, X, Y
      END

struct block { double a; int b; };      /* Source file is fccmn2.c */
void sub1_( )
{
  extern struct block __blnk_;
  extern struct block _named_;

  __blnk_.a = 3.1415927;
  __blnk_.b = 61659;

  _named_.a = 2.7182818;
  _named_.b = 95616;
}

Строка запуска компилятора

        cc -c fccmn2.c
        fc fccmn.f fccmn2.o

Результат

        A= 3.14159270  B= 61659
        X= 2.71828180  Y= 95616

Примечание.

В С именованный и неименованный COMMON блоки представляются структурами с предопределенными именами.

Передача и возврат целых и вещественных переменных

Пример 6.2

                                            ! Source file is fcir.f
      PROGRAM MAIN
      INTEGER*4 I /0/
      REAL*4    A /0.0/
      CALL SUB1(I,A)
      PRINT *, I,A
      END

void sub1_(int *j, float *b)            /* Source file is fcir2.c */
{
   *j=1234567;
   *b=9876.543;
}

Строка запуска компилятора

        cc -c fcir2.c
        fc -sa fcir.f fcir2.o

Результат

      I= 1234567   A= 9876.543

Примечание.

По умолчанию список аргументов FORTRAN программ на этапе компиляции помещается в статическую область памяти программного сегмента. Опция -sa требует помещения списка аргументов в стек. Данная опция используется при вызове С программ из FORTRAN.

Параметры j и b описываются в sub1_ как указатели,т.к. в FORTRAN параметры вызываемой программы передаются через ссылку.

Пример 6.3

      PROGRAM MAIN                          ! Source file is fcfunc.f
      REAL*4 ADDEM, B1 /43.0/, B2 /12.0/
      INTEGER*4 IADDEM, J1 /43/, J2 /12/
      PRINT *, ADDEM(B1,B2)
      PRINT *, IADDEM(J1,J2)
      END

float addem_( float *a1, float *a2 )    /* Source file is fcfunc2.c */
{
    return( *a1+ *a2 );
}
int iaddem_( int *i1, int *i2 )
{
   return( *i1 + *i2 );
}

Строка запуска компилятора

        cc -c fcfunc2.c
        fc -sa fcfunc.f fcfunc2.o

Результат

        ADDEM= 55.00000
        IADDEM= 55

Пример 6.4

      PROGRAM MAIN                          ! Source file is fcfunc1.f
      REAL*4 ADDEM,B1/43.0/,B2/12.0/
      PRINT *,ADDEM(%VAL(B1),%VAL(B2))
      END

float addem_(float a1,float a2)         /* Source file is fcfunc3.c */
{
    return(a1+a2);
}

Строка запуска компилятора

        cc -c fcfunc3.c
        fc -sa fcfunc1.f fcfunc3.o

Результат

        ADDEM= 55.00000

Примечание.

Пример 6.4 является вариантом примера 6.3. Используется встроенная функция компилятора FORTRAN %VAL для передачи параметров функции ADDEM по значению. Функция %VAL может использоваться только в строке вызова ADDEM со списком фактических параметров.

Передача и возврат текстовых переменных

Пример 6.5

      PROGRAM MAIN                          ! Source file is fcchar.f
      CHARACTER*11 CVAR1 /' '/
      CHARACTER*6  CVAR2 /' '/
      CALL SUB1 (CVAR1, CVAR2)
      PRINT *, CVAR1, CVAR2
      END

#include < string.h>                      /* Source file is fcchar2.c */
void sub1_(char *str1,char *str2,int d1,int d2)
{
   (void) strncpy( str1, "1234567890", d1);
   (void) strncpy( str2, "abcde", d2);
}

Строка запуска компилятора

        cc -c fcchar2.c
        fc -sa fcchar.f fcchar2.o

Результат

        CVAR1= 1234567890

Примечание.

В описании текстовых переменных CVAR1, CVAR2 в MAIN программе резервируется память для дополнительного символа (конца строки), поскольку при вызове функции sub1_ во время копирования данных в эти переменные дописывается символ конца строки.

Параметры d1, d2 добавляются в конце списка параметров sub1_ в соответствии с соглашениями о передаче текстовых параметров компилятора FORTRAN. Данные параметры передаются по значению и соответствуют декларируемым в MAIN программе длинам CVAR1, CVAR2. Поэтому они не описываются как указатели и компилятор FORTRAN помещает их значения в стек.

Пример 6.6

      PROGRAM MAIN                          ! Source file is fccfunc.f
      INTEGER VAL1, VAL2
      CHARACTER*10 DIGITS /'0123456789'/
      CHARACTER*30 MAKESTR
      PRINT 400, MAKESTR (DIGITS,VAL1,VAL2), VAL1, VAL2
  400 FORMAT('String=',A,'|Val1=',I3,'|Val2=',I3,'|')
      END

#include < string.h>                      /* Source file is fccfunc2.c */
void makestr_(char cstr[], long int cstr_len, char *arg1,
long int *num1, long int *num2, int arg1_len )
{
  (void) strcpy( cstr, "abcde      " );
  (void) strcat( cstr, arg1 );
  *num1 = cstr_len;
  *num2 = arg1_len;
}

Строка запуска компилятора

        cc -c fccfunc2.c
        fc -sa fccfunc.f fccfunc2.o

Результат

        String=abcde      0123456789|Val1= 30|Val2= 10|

Примечание.

В соответствии с соглашениями о передаваемых параметрах компилятор FORTRAN транслирует CHARACTER функцию MAKESTR в подпрограмму,в которой первым аргументом является адрес,а вторым - длина текстовой переменной возвращаемого значения. Функция makestr_ имитирует подпрограмму MAKESTR и имеет тип void. В начале списка параметров makestr_ добавляются два дополнительных аргумента - адрес и максимальная длина текстовой переменной результата. В конце списка параметров также добавляется дополнительный аргумент (длина переменной DIGITS).Второй и последний дополнительные аргументы передаются по значению и соответствуют длинам декларируемых в MAIN программе переменных MAKESTR и DIGITS.

Передача и возврат комплексных переменных и структур

Пример 6.7

      PROGRAM MAIN                          ! Source file is fccplx.f
      COMPLEX*8 CX /(0.0,0.0)/
      CALL SUB1 (CX)
      PRINT *, CX
      END

void sub1_( struct { float r,i;} *cxs )  /* Source file is fccplx2.c */
{
  cxs-> r=123.45;
  cxs-> i=678.90;
}

Строка запуска компилятора

        cc -c fccplx2.c
        fc -sa fccplx.f fccplx2.o

Результат

        CX = ( 123.4500 , 678.9000 )

Пример 6.8

      PROGRAM MAIN                          ! Source file is fcxfunc.f
      COMPLEX*8 MAKECX8, ANS8
      COMPLEX*16 MAKECX16, ANS16
      REAL*4 B1 /5.0/, B2 /7.0/
      REAL*8 D1 /5.0/, D2 /7.0/
      ANS8 = MAKECX8(B1,B2)
      ANS16 = MAKECX16(D1,D2)
      PRINT *, ANS8
      PRINT *, ANS16
      END

                                       /* Source file is fcxfunc2.c */
typedef struct {float r, i;} complex8_t;
typedef struct {double r, i;} complex16_t;
void makecx8_( complex8_t *cx, float *a1, float *a2 )
{
  cx-> r = *a1 + *a2;
  cx-> i = *a1 - *a2;
}

void makecx16_( complex16_t *cx, double *a1, double *a2 )
{
  cx-> r = *a1 + *a2;
  cx-> i = *a1 - *a2;
}

Строка запуска компилятора

        cc -c fcxfunc2.c
        fc -sa fcxfunc.f fcxfunc2.o

Результат

       ANS8 = ( 12.00000 , -2.000000 )
       ANS16 = ( 12.0000000000000 , -2.00000000000000 )

Примечание.

В начало списка параметров функций makecx8_ и makecx16_ добавляется дополнительный аргумент (адрес результата). Возвращаемое makecx8_ и makecx16_ значение является структурой. В данном примере используется механизм возврата значений,принятый по умолчанию компилятором С (через сегмент данныж памяти).

Пример 6.9

В данном примере используется новый(стековый) механизм возврата значений. Строка запуска компилятора С включает дополнительную опцию:

         cc -c -compat rrf=stack fcxfunc3.c

Данная опция может применяться при компиляции функций С, у которых возвращаемый результат является структурой и передается по значению.

Ниже приводится модифицированный исходный код модуля fcxfunc3.c, отличающийся от fcxfunc2.c

                                     /* Source file is fcxfunc3.c */
typedef struct {float r, i;} complex8_t;
typedef struct {double r, i;} complex16_t;

complex8_t makecx8_( float *a1, float *a2 )
{
 complex8_t cx;
  cx.r = *a1 + *a2;
  cx.i = *a1 - *a2;
  return cx;
}

complex16_t makecx16_( double *a1, double *a2 )
{
 complex16_t cx;
  cx.r = *a1 + *a2;
  cx.i = *a1 - *a2;
  return cx;
}

Результат

       ANS8 = ( 12.00000 , -2.000000 )
       ANS16 = ( 12.0000000000000 , -2.00000000000000 )

Литература

1. CONVEX Interlanguage Programming Guide, First Edition, 1992

2. CONVEX C Guide, Second Edition, 1993

3. CONVEX FORTRAN User's Guide, Tenth Edition, 1992


The file was converted from TeX source by FunnyTeX utility by Mike Krutikov