Организация интерфейса между программами на Delphi и Microsoft Fortran

В недалеком прошлом эксплуатировались электронно-вычислительные машины (ЭВМ) серий ЕС и СМ, так называемые большие и мини ЭВМ третьего поколения. В НИИ, проектных, конструкторских, технологических предприятиях, учебных заведениях и заводах велись работы по автоматизации проектирования, разрабатывались библиотеки программ научных исследований. На базе ЭВМ были организованы информационно-вычислительные центры (ИВЦ), отделы САПР (систем автоматизированного проектирования), обслуживаемые коллективом специалистов. Взаимодействие инженеров-пользователей с ЭВМ осуществлялось через специалистов ИВЦ, для чего пользователю необходимо было владеть программированием.

Основными языками программирования были Fortran 4, а затем Fortran 77, ориентированные на программирование инженерно-технических задач. На языке Fortran было написано огромное количество программного обеспечения, созданы специализированные библиотеки программ, например, математические. При разработке систем автоматизированного проектирования на языке Fortran написаны и специализированные подпрограммы, например, расчета режимов резания, припусков на механическую обработку, нормирования технологических операций и т.п.

В 90-е годы произошла смена технического и программного обеспечения автоматизированного проектирования. Получили широкое распространение персональные компьютеры четвертого поколения, изменилось программное обеспечение и методы взаимодействия пользователя с ЭВМ. На первое место вышли языки программирования: C, Pascal, FoxPro, появились системы объектно-ориентированного и визуального программирования: Microsoft Visual C++, Borland Delphi, Microsoft Visual Basic и др. Стало очевидно, что старый Fortran не может конкурировать с такими системами, как Visual C++ и Delphi, что перевод программного обеспечения с Fortran на Visual C++ или Delphi задача трудоемкая и в современных условиях почти невыполнимая. Программное обеспечение, созданное на Fortran, стали забывать, перечеркивая тем самым многолетний труд тысяч предприятий, занимающихся его разработкой в прошлые годы.

В статье рассматривается подход о возможности применения программного кода, написанного на Fortran при программировании на современном языке Borland Delphi, что позволяет использовать давно забытые программы при решении современных научно-технических задач.

Выполняемые файлы Windows известны в двух вариантах: программы и библиотеки динамической компоновки (dynamic link library, DLL). В среде Delphi создать DLL очень просто, однако некоторые проблемы порождаются самой природой DLL. Создание DLL в Windows не всегда так просто, как кажется, поскольку между DLL и вызывающей программой должны быть согласованы условия вызова, типы параметров и другие детали. С целью использования программного кода, написанного на Fortran при программировании на Borland Delphi, можно воспользоваться следующей схемой (рис.1):

1. Удалить из Fortran-программы фрагменты кода, в котором реализован ввод-вывод информации (опрераторы READ и WRITE).

2. Превратить Fortran-программу в библиотеку динамической компоновки DLL.

3. На Delphi разработать программный интерфейс, ввод-вывод информации и организовать обращение к подпрограммам фортрановской библиотеки динамической компоновки DLL.

организация программного обеспечения на Delphi и Microsoft Fortran Рис.1 Схема организации программного обеспечения на Delphi и Microsoft Fortran

Для создания фортрановской библиотеки динамической компоновки и организации её взаимосвязи с программой на Delphi можно, например, воспользоваться Fortran PowerStation 4.0, входящего в продукт Microsoft Developer Studio (1995 г), полностью совместимого с Fortran IV, Fortran 77 и Fortran 90 (рис.2).

Окно разработки программ в Fortran PowerStation 4.0

Рис.2 Окно разработки программ в Fortran PowerStation 4.0

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

1. Несколько прикладных программ могут обращаться к одной и той же DLL, что снижает общий объем памяти, необходимый системе.

2. Используя DLL, прикладные программы могут иметь очень малый размер

3. Можно изменять функции в DLL без компиляции прикладных программ. Это позволяет легко модернизировать прикладные программы.

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

При создании библиотек динамической компоновки DLL на языке Fortran необходимо воспользоваться метакомандами, предусмотренными в Microsoft Fortran PowerStation 4.0 .

Метакоманды объявляют расширенные атрибуты для установленных переменных.

Синтаксис метакоманды:

$ATTRIBUTES список атрибутов:: список переменных

MS$ATTRIBUTES список атрибутов:: список переменных

Список атрибутов

Один или большее количество расширенных атрибутов, объявленных для переменных. Если перечислены больше чем один атрибут, они должны быть отделены запятыми.

Список переменных

Один или большее количество переменных и (или) процедур. Если перечислены больше чем одна переменная и (или) процедура, то они должны быть отделены запятыми.

Используются следующие основные атрибуты:

ALIAS

 C

 DLLEXPORT

 DLLIMPORT

 EXTERN

 REFERENCE

 STDCALL

 VALUE

 VARYING

Можно назначать больше чем один атрибут к множеству переменных в одной метакоманде. Атрибуты отделяются друг от друга запятыми (,), атрибуты отделяются от переменных двойным двоеточием (::), а переменные отделяются друг от друга запятыми. Все атрибуты относятся ко всем перечисленным переменным. Например:

!MS$ATTRIBUTES REFERENCE, VARYING::A,B,C

В этом примере, к переменным A, B, и C назначены атрибуты REFERENCE, VARYING. Единственное ограничение на число атрибутов и переменных — то, что метакоманда должна располагаться в одной строке.

Идентификатор переменной или процедуры должен быть простым.

Например, нельзя включать в список переменных или процедур размерности массивов:

!MS$ATTRIBUTES C:: A(10) Это незаконно.

Атрибут ALIAS. Атрибут ALIAS позволяет определить внешнее название для подпрограммы или общего блока. Название может отличаться от названия, использованного в объявлении.

Форма атрибута ALIAS:

ALIAS: строка

строка — символьная константа.

Со строкой не выполняется никаких преобразований. Например, символы нижнего регистра не преобразовываются к верхнему регистру.

В пределах исходного файла, подпрограмма может быть упомянута только её названием, данным в его объявлении. Вне исходного файла, подпрограмма может быть упомянута только названием её псевдонима (ALIAS).

Вы можете также использовать атрибут ALIAS в блоке INTERFACE, чтобы переопределить название подпрограммы в другом исходном файле, который Вы хотите вызвать.

Атрибут ALIAS отменяет атрибут C. Если атрибут C используется в подпрограмме наряду с атрибутом ALIAS, подпрограмме дают соглашение о вызовах C, но не соглашение об именах C.

Например, в языке Fortran:

INTERFACE
SUBROUTINE happy
!MS$ ATTRIBUTES C, VARYING, ALIAS:'OtherName' :: happy
END SUBROUTINE
END INTERFACE

Атрибуты C и STDCALL. Когда используются подпрограммы, написанные на языке C, ассемблере, Borland Delphi с подпрограммами, написанными на Fortran, необходимо определить порядок следования данных. Можно выбрать два альтернативных соглашения о вызовах: C и STDCALL.

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

Таблица 1

Различие в вызовах подпрограмм при использовании атрибутов C и STDCALL

Свойства

Соглашение C

Соглашение STDCALL

Значение по

умолчанию

Добавляет вначале имени подпрограммы символ подчеркивания

Да

Да

Да

Добавляет номер в аргумент подпрограммы

Нет

Да

Да

Обращение без учета регистра

Нет

Нет

Да

Параметры считываются справа налево

Да

Да

Да

Очистка стека вызывающей программы

Да

Нет

Нет

Переменное число параметров

Да

Нет

Нет

Значение по умолчанию и соглашение STDCALL восстанавливают стек когда процедура завершает выполнение. Генерируется меньшее количество кода, чем соглашение C, в котором этот код генерируется при каждом обращении к процедуре.

Параметры при обращении к подпрограммам, определенным атрибутами C и STDCALL, передаются значением, но это может быть изменено. Подпрограммы, использующие стандартные соглашения Fortran, передают параметры ссылкой, если не переопределено атрибутом VALUE.

Имена подпрограмм, использующих атрибут C, изменяются автоматически, чтобы обеспечить согласование в именах, используемое в языке C. Внешние названия (имена) приводятся к нижнему регистру и начинаются с символа подчеркивания ( _ ). Чтобы использовать название, содержащее прописные буквы, следует использовать атрибут ALIAS.

Внешние названия (имена) подпрограмм, использующих атрибут STDCALL, изменяются на нижний регистр, начинаются с символа подчеркивания ( _ ), в конце ставится знак (@) и число байтов, выделяемых для параметров. Например, подпрограмма с атрибутом STDCALL, названная NAME, имеющая четыре параметра целого типа INTEGER(2) будет иметь внешнее имя _name@16.

Атрибуты DLLEXPORT – DLLIMPORT. Данные и код динамически компонуемой библиотеки загружаются в то же самое адресное пространство, что и данные и код программы, которая ее вызывает. Однако в Фортране, переменные и подпрограммы, объявленные в программе и в DLL не будут разделены, если не использовать директивы компилятора DLLIMPORT и DLLEXPORT. Эти директивы дают возможность компилятору и компоновщику правильно обращаться к частям адресного пространства так, чтобы данные и подпрограммы были разделены.

Директива DLLEXPORT объявляет, что общий блок в DLL принадлежит одной подпрограмме и экспортируется в другую программу или DLL.

Директива DLLIMPORT используется в вызывающей программе, чтобы сообщить компилятору, что общий блок импортируется из другой подпрограммы или DLL.

Одна связь (ссылка) между директивами DLLEXPORTDLLIMPORT должна быть установлена для каждого общего блока, общедоступного между программой и DLL или между двумя DLL.

Атрибуты DLLEXPORT и DLLIMPORT определяют интерфейс динамически компонуемой библиотеки (DLL) в процессах, которые её используют. Можно также применять эти атрибуты к данным. Объявление процедур или информационных объектов с атрибутом DLLEXPORT устраняет потребность в определении модуля файла (.DEF).

Атрибут DLLEXPORT объявляет, что функции или данные экспортируются в другие приложения или DLLS и компилятор производит наиболее эффективный код. Программа, которая использует данные, определенные в DLL, импортирует их.

Атрибут DLLIMPORT объявляется внутри модуля программы, который импортирует данные.

Например:

SUBROUTINE ARRAYTEST(arr)

!MS$ ATTRIBUTES DLLEXPORT :: ARRAYTEST

REAL(4) arr(3, 7)

INTEGER i, j

DO i = 1, 3

DO j = 1, 7

arr (i, j) = 11.0 * i + j

END DO

END DO

END SUBROUTINE

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

Атрибут REFERENCE. Атрибут REFERENCE применяется только к формальным переменным. Означает, что параметр передается ссылкой, а не значением.

Атрибут VALUE. Атрибут VALUE может применяться только к формальным переменным. Означает, что параметр передается значением.

В следующем примере целое число x передается значением:

SUBROUTINE Subr (x)
INTEGER x
!MS$ ATTRIBUTES VALUE :: x

Атрибут VARYING. Можно вызывать подпрограммы с переменном числом параметров при включении атрибутов C и VARYING в вашем интерфейсе к подпрограмме. Атрибут VARYING освобождает ФОРТРАН от предписания номера соответствия параметров в подпрограммах.

Использование приведенных атрибутов в программах на Fortran можно проиллюстрировать на следующем примере:

SUBROUTINE RAPNOO(MD,VZ,KTO,KM,HGRO,VP,HRD,VOD,HOD,A,VHR,BYD,BPA,
*DCB,SBP,TOP,DOMX,DOPMN,NM,NOZ,VPD,SPO,GSO)
!MS$ATTRIBUTES C,DLLEXPORT::RAPNOO
!MS$ATTRIBUTES REFERENCE::MD,VZ,KTO,KM,HGRO,VP,HRD,VOD,HOD,A,VHR
!MS$ATTRIBUTES REFERENCE::BYD,BPA,DCB,SBP,TOP,DOMX,DOPMN,NM,NOZ
!MS$ATTRIBUTES REFERENCE::VPD,SPO,GSO

Директива DLLEXPORT объявляет, что подпрограмма RAPNOO в DLL принадлежит одной подпрограмме и экспортируется в другую программу или DLL с использованием соглашения о вызовах C, значения переменных передаются по ссылке (REFERENCE).

Обращение к Fortran — подпрограмме организовывается на Delphi следующим образом:

1. В разделе описания типов Type следует объявить процедуру, например с именем RAPNOO_DLL:

procedure RAPNOO_DLL(var MD, VZ, KTO, KM, HGRO, VP, HRD, VOD, HOD, A, VHR, BYD, BPA, DCB, SBP, TOP, DOMX, DOPMN, NM, NOZ, VPD, SPO, GSO : SINGLE); stdcall; external 'RAPNOO.DLL' name 'rapnoo';

2. При передаче параметров типа real необходимо согласование по количеству байт, на Delphi использовать вещественные числа типа Single (4 байт).

3. Использовать передачу параметров по ссылке.

4. Использовать программу Tdump.exe для определения имени DLL-файла (поставляется совместно с Borland Delphi 7).

5. В Fortran использовать аттрибуты C, STDCALL,REFERENCE.

6. При передаче двумерных массивов следует учитывать, что Паскаль хранит в памяти элементы двумерного массива по строкам, а Fortran по столбцам, поэтому для передачи массива в Fortran-программу, массив нужно перевернуть, т.е. поменять строки со столбцами.

Выводы:

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

Александр Малыгин

Объект обсуждения - программное обеспечение для выполнения автоматизированного конструкторского и технологического проектирования, разработки управляющих программ, вопросы, связанные с разработкой прикладных САПР.

7 Комментарии “Организация интерфейса между программами на Delphi и Microsoft Fortran

    1. Есть и достаточно много, т.к. на Фортране пришлось программировать достаточно долго.
      Спрашивайте, что именно Вам хотелось бы прочитать.

      1. Здравствуйте, уважаемый администратор! Очень благодарен Вам приведенную информацию. В той организации, где я сецчас работаю, возникла описанная Вами проблема — есть старые разработчики программ на Фортане, но на данный момент результатами их труда воспользоваться невозможно. Необходимо совместить их расчетный опыт и современные возможности визуализации результатов и организации интерфейса. Вы можете посоветовать, что и где можно почитать по вопросам взаимодействия Fortran и Delphi. Очень необходим уровень пошаговых руководств «для чайников». (Вот удачный пример: you tube. com/watch?v=sjsHj5HSLbw) Чтобы внешняя dll-ка на Fortran складывала два числа, введенные в форме Delphi. Пока что в Сети ничего толкового не удалось найти. Также интересна организация работы с массивами. Найденные дискуссия на форумах говорят о том, что вопрос не так однозначен. Также интересно использование функций библиотеки IMSL в Delphi… В общем, если Вы прольете свет на такого рода вопросы, то я буду Вам очень благодарен. Я готов Вам отблагодарить, насколько позволит зарплата инженера, если это будет необходимо. Тема действительно очень интересна, но методически проработана слабо. Буду благодарен Вам за ответ.

        1. Я не знаю Вашей предметной области, квалификацию программистов и используемые языки программирования. Поэтому сейчас могу рассуждать только в общем.
          Проблемы я не вижу вообще. Все решается достаточно просто при одном условии. Вы обязательно должны иметь хорошего программиста, может двух, которые свободно программируют на Фортране и (Delphi или Си). Все остальное написано в моей статье, которую эти программисты должны свободно понять.
          На мой взгляд, такой путь создания новых программ – плохой. Он подходит только для того, чтобы старые разработки, написанные на Фортране, не выбрасывать. Но создавать новые разработки по такой технологии – глупость.
          Если говорить о будущем Ваших разработок, то надо их делать на одном языке. Любому программисту значительно проще потратить 2-3 месяца для изучения второго языка программирования, чем лепить программу из разных модулей, написанных на разных языках.

          Хороших статей и видео по данной теме не встречал.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *