Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 28.02.2011, 12:08   #11
Vago
Форумчанин
 
Регистрация: 15.01.2010
Сообщений: 948
По умолчанию

"Завтра" наступило

1. В общем, берём суперпрограмму вычисления среднего арифметического значений одномерного массива на ФОРТРАН-66 Как она ко мне попала - неважно. Может, студенты за зачёт набили и выверили, может - древнюю ленту с ЕС-ки удалось прочитать... Неважно...
Код:
      DIMENSION A(200)
      READ (1,21) N
   21 FORMAT (I3)
      READ (1,22) (A(I),I=1,N)
   22 FORMAT (16F5.1)
      WRITE(3,23)
   23 FORMAT(1X, 'THE SOURCE MATRIX:')
      DO 30 I=1,N
   30 WRITE(3,32) I,N
   32 FORMAT(1X,'A(',I3,')=',F7.1)
      S = 0.
      DO 35 I = 1,N
   35 S = S + A(I)
      S = S/FLOAT(N)
      WRITE(3,37) S
   37 FORMAT(1X,'S=',F7.1)
      STOP
      END
Проверкой возможного выхода N за границы массива (или нулевого N) пока не забиваем себе голову

1.a. Не связанное с Основной задачей Отступление.
Судя по отсутствию оператора OPEN в Вашем примере, запускать эту программу на персоналке у вас никто пытался. Потому что, если запустите - получите, скорее всего, кучу непонятных ошибок, связанных с вводом-выводом. Это потому что программа не знает, откуда физически читать данные. К цифирке "1" в операторе READ не привязан конкретный файл. Поэтому в свой пример, чтобы проверить его как автономную программу, я добавлю два оператора OPEN (а заодно, по привычке, - добавлю, для удобочитаемости, отступы, задекларирую все переменные явно, оформлю циклы в стиле ФОРТРАН-77 и, опять же для удобочитаемости, соберу операторы FORMAT в одном месте. Но Вы этого можете не делать ).
Код:
      PROGRAM SAr

C        Лучше приучить себя объявлять явно ВСЁ !
         REAL A(200), S
         INTEGER N

         OPEN (UNIT=1,FILE='INPUT.DAT')
         READ (1,21) N
         READ (1,22) (A(I),I=1,N)
         OPEN (UNIT=3, FILE='CON')
         WRITE(3,23)
C        СДЕЛАЕМ ЦИКЛЫ ЧУТЬ БОЛЕЕ УДОБОЧИТАЕМЫМИ
         DO I = 1, N
            WRITE(3,32) I,A(I)
         END DO
         S = 0.
         DO I = 1,N
            S = S + A(I)
         END DO
         S = S / FLOAT(N)
         WRITE(3,37) S

C        ОПЯТЬ ЖЕ ДЛЯ УДОБОЧИТАЕМОСТИ - ВСЕ ФОРМАТЫ - В ОДНОМ МЕСТЕ
   21    FORMAT (I3)	
   22    FORMAT (16F5.1)
   23    FORMAT(1X, 'THE SOURCE MATRIX:')
   32    FORMAT(1X,'A(',I2,')=',F7.1)
   37    FORMAT(1X,'S=',F7.1)

         STOP
      END
Создаём файлик input.dat с исходными данными :
Код:
  6
 1.0  2.0  3.0  4.0  5.0  6.0
Транслируем программу, запускаем, получаем:
110228.jpg
(Вывод одномерного массива в столбик - ну это - святое! ).

Последний раз редактировалось Vago; 28.02.2011 в 16:28.
Vago вне форума Ответить с цитированием
Старый 28.02.2011, 12:15   #12
Obey-Kun
Линуксоид
Участник клуба
 
Аватар для Obey-Kun
 
Регистрация: 31.07.2009
Сообщений: 1,403
По умолчанию

Лучше таки вручную переводите на C или на C++. Поддерживать программу будет проще. Особенно в будущем.
Я схожу с ума или это глючит реальность?
Jabber ID: obey@obey.su
Obey-Kun вне форума Ответить с цитированием
Старый 28.02.2011, 12:17   #13
Vago
Форумчанин
 
Регистрация: 15.01.2010
Сообщений: 948
По умолчанию

3. Оформляем фортрановскую основную программу в виде подпрограммы-функции. КАК ОБЪЯВИТЬ ТОЧКУ ВХОДА - ПРОЧИТАЙТЕ В ДОКУМЕНТАЦИИ К СВОЕМУ КОМПИИЛЯТОРУ! Ввод в Фортране - закомментируем (всё будет передаваться извне, из C++), вывод пока, для отладки, оставляем. Строим dll (sar_for.dll она у меня будет называться). КАК строим - это будет зависеть от конкретной Фортран-среды, с которой Вы будете работать.
Код:
C     Оформляем вычисления, как ФУНКЦИЮ
      INTEGER FUNCTION SAr(N,A,S)

C COMPILER-SPECIFIC DECLARATION !!!
!DEC$ ATTRIBUTES DLLEXPORT :: SAr

         REAL A(1), S
         INTEGER N

C        УДАЛЯЕМ ВЕСЬ ВВОД
C I/O    OPEN (UNIT=1,FILE='INPUT.DAT')
C I/O    READ (1,21) N
C I/O    READ (1,22) (A(I),I=1,N)
         OPEN (UNIT=3, FILE='CON')
         WRITE(3,23)

         DO I = 1, N
            WRITE(3,32) I,A(I)
         END DO

         S = 0.
         DO I = 1,N
            S = S + A(I)
         END DO
         S = S / FLOAT(N)
         WRITE(3,37) S

c I/O	21    FORMAT (I3)	
c I/O   22    FORMAT (16F5.1)
   23    FORMAT(1X, 'THE SOURCE MATRIX:')
   32    FORMAT(1X,'A(',I2,')=',F7.1)
   37    FORMAT(1X,'S=',F7.1)

C        Меняем STOP на RETURN
C        STOP
         SAr = 0
         RETURN

      END
4. Пишем вызывающую C++ программку.
Код:
#include <windows.h>
#include <iostream>
using namespace std;

int main() {

   HMODULE  hDll ;
   int      rCode = 0;
   
   // Пытаемся загрузить DDL
   hDll = LoadLibrary( "Release/sar_for.dll" ) ; // handler to the loaded DLL
   if ( hDll == NULL ) {   // Не нашли DLL
      cerr << "COULD NOT FIND DLL !" << endl ;
      return -1 ;
   }

   // Пытаемся найти ф-ю в DLL
   typedef long __stdcall SAr( int*, float*, float* ) ;     // Прототип фортрановской ф-ии
   // Фортран запишет имя ф-ии ЗАГЛАВНЫМИ БУКВАМИ!! Поэтому в параметрах GetProcAddress "SAR", а не "SAr"!
   SAr* pSAr = (SAr*) GetProcAddress( hDll, "SAR" ) ; 
   if ( pSAr == NULL ) {   // Не нашли ф-ю
      cerr << "COULD NOT FIND FUNCTION ENTRY. LIBRARY CORRUPTED?" << endl ;
      return -1 ;
   }

   // Тестовые исходные данные
   int n = 6 ;
   float a[] = {1., 2., 3., 4., 5., 6. } ;
   float s ;

   // Собственно ВЫЗОВ
   rCode = (long) (*pSAr)( &n, a, &s ) ;
   if ( rCode == 0 ) {
      cout << "S after call = " << s << endl ;
   }

   return rCode ;

}
По-хорошему, она должна быть напичкана #ifdef'ами (для debug и для release-версий DLL, для DLL, построенных разными Фортран-компиляторами, может быть даже для возможной удачной статической линковки. Но мы пока не будем забивать ими ни текст функции, ни голову).

5. Ну и... Всё...
110228_2.jpg

Последний раз редактировалось Vago; 28.02.2011 в 15:41.
Vago вне форума Ответить с цитированием
Старый 02.03.2011, 15:35   #14
Davlet M
Пользователь
 
Регистрация: 27.08.2009
Сообщений: 34
По умолчанию

Большое спасибо за труд, буду разбираться!)
Davlet M вне форума Ответить с цитированием
Старый 03.03.2011, 12:57   #15
Vago
Форумчанин
 
Регистрация: 15.01.2010
Сообщений: 948
По умолчанию

Не за что. Я смотрю, Вы с комплексными числами будете работать. Вот Вам тогда ещё одна болванка.

Фортрановская подпрограмма возвращает модуль единственного комплексного аргумента.
Код:
      REAL FUNCTION CPXMOD( A )

!DEC$ ATTRIBUTES DLLEXPORT :: CPXMOD

         COMPLEX A

         OPEN (UNIT=3, FILE='CON')

         WRITE (3,101) A
         CPXMOD = CABS( A )
         WRITE (3, 102) CPXMOD

  101    FORMAT ( 'A = (', F5.1, ' +', F5.1, 'i )' )	
  102    FORMAT ( '|A| = ', F5.2 )

         RETURN

      END
Вызывающая программка выглядит уже чуть пожизненнее
Код:
#include <windows.h>
#include <iostream>
#include <complex>
using namespace std;

#ifndef __FORTRAN_DLL__
extern "C" float __stdcall CPXMOD( complex<float>* ) ;
#endif

int main() {

#ifdef __FORTRAN_DLL__   
   HMODULE hDll ;
#ifdef NDEBUG
   hDll = LoadLibrary( "Release/fordll.dll" ) ; 
#else
   hDll = LoadLibrary( "Debug/fordlld.dll" ) ; 
#endif
   if ( hDll == NULL ) {   
      cerr << "COULD NOT FIND DLL !" << endl ;
      return -1 ;
   }

   typedef float __stdcall CPXMOD( complex<float>* ) ; 
   CPXMOD* pCpxMod = (CPXMOD*) GetProcAddress( hDll, "CPXMOD" ) ; 
   if ( pCpxMod == NULL ) {  
      cerr << "COULD NOT FIND FUNCTION ENTRY. LIBRARY CORRUPTED?" << endl ;
      return -1 ;
   }
#endif

   complex<float> A(1.,1.) ;
   float    aMod ;

#ifdef __FORTRAN_DLL__   
   aMod = (float) (*pCpxMod)( &A ) ;
#else
   aMod = CPXMOD( &A ) ;
#endif

   cout << "|A| after call = " << aMod << endl ;

   return 0 ;

}
В принципе, ничего в таком сопряжении страшного нет. Нужно помнить:
1. Все параметры подпрограмм в Фортране передаются по адресу.
2. Двумерные массивы Фортран располагает по столбцам.
3. Соответствие типов, естественно.
4. Decoration rules фортран-компилятора.

Удачи! Спрашивайте, ежели что...
Vago вне форума Ответить с цитированием
Старый 03.03.2011, 16:51   #16
Davlet M
Пользователь
 
Регистрация: 27.08.2009
Сообщений: 34
По умолчанию

еще раз спасиб, но что-то не получается создать точку входа в длл(( информации о том как это сделать в с++ билдере не нашел((
Davlet M вне форума Ответить с цитированием
Старый 03.03.2011, 18:00   #17
Vago
Форумчанин
 
Регистрация: 15.01.2010
Сообщений: 948
По умолчанию

Так создаётся ж она НЕ в С++! DLL-то фортрановская? Значит, в Фортране она назначается, а программа на C++ её потом должна найти.

Какой Фортран? M$ / Digital / Compaq?.. Lahey?.. Intel?..
Vago вне форума Ответить с цитированием
Старый 03.03.2011, 18:05   #18
Davlet M
Пользователь
 
Регистрация: 27.08.2009
Сообщений: 34
По умолчанию

Microsoft developer studio
Davlet M вне форума Ответить с цитированием
Старый 03.03.2011, 18:12   #19
Vago
Форумчанин
 
Регистрация: 15.01.2010
Сообщений: 948
По умолчанию

1. Какая "Студия"? 6-я или свежее?
2. Help -> About -> поползёт список подключенных компиляторов. Что там про Фортран будет (включая фирму и версию)?
Vago вне форума Ответить с цитированием
Старый 03.03.2011, 18:15   #20
Davlet M
Пользователь
 
Регистрация: 27.08.2009
Сообщений: 34
По умолчанию

Fortran power station v 4. больше ничего нет
Davlet M вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Создание dll на с++ для 1с8 zladej Общие вопросы C/C++ 0 05.07.2010 13:11
Создание dll John_chek Общие вопросы Delphi 3 24.09.2007 14:26
Создание dll файла для работы с БД Nadya БД в Delphi 2 15.02.2007 12:54