Реферат: Использование Prolog совместно с другими ЯП
Название: Использование Prolog совместно с другими ЯП Раздел: Рефераты по информатике Тип: реферат | ||||||||||||||||||||||||||||||||||
Использование Prolog совместно с другими ЯП. Понятие Dll. Вспомним процесс программирования в DOS. Преобразование исходного текста в машинный код включал в себя 2 процесса: компиляцию и линковку. Во время линковки в код программы помещались не только объявления функций и процедур, но и их полный код. В многозадачной среде подобный подход был бы весьма расточителен, так как огромное количество функций, отвечающих за прорисовку элементов пользовательского интерфейса, за обращение к системным ресурсам и т.п. дублировались в каждой программе. В качестве решения возникшей проблемы была предложена концепция динамической компоновки (см. рис. 1).
DLL (библиотека динамической связи) – файл, выступающий в качестве коллективной библиотеки предикатов, которые могут быть использованы одновременно в нескольких приложениях. Prolog способен генерировать DLL, включать DLL статически и загружать динамически. Вызов в программе на VP процедур и функций на других языках. Прежде чем вызвать процедуры и функции на других языках их нужно объявить как внешний предикат, упомянув, что он осуществляется на другом языке. При этом необходимо знать количество и порядок входных параметров: GLOBAL PREDICATES procedure add(integer A, integer B, integer C) – (i,i,o) language pascal Замечание: обратите внимание, что в VP явно указывается язык процедуры Передача входных/выходных параметров и возвращение значений. Размер входных параметров определен однозначно и зависит только от объявленного типа. Выходной параметр – 32 битный указатель на область памяти, где хранится выходное значение. Следует отметить, что функции на Pascal не могут возвращать значения в формате чисел с плавающей точкой, а функции C - структуры (но могут, конечно, возвращать указатели на них). Многочисленные декларации. Предикат VP может иметь различные комбинации входных/выходных параметров, и для каждой из них необходима отдельная процедура. Идентификаторы, используемые в Prolog должны совпадать с идентификаторами в библиотеке + суффикс _X, где X – целое число (порядковый номер процедуры, нумерация начинается с 0). Если существует только один вариант, то суффикс отсутствует. Рассмотрим пример: GLOBAL PREDICATES subtraction(integer, integer, integer) – (i,i,o), (i,o,i), (o,i,i), (i,i,i) language C change(integer, integer) – (i,o) language C GOAL subtraction(2,2,X), write(“2-2=”,X), nl, subtraction(2,Y,5), write(“2-5=”,Y), nl, subtraction(Z,5,4), write(“5-4=”,X), nl, subtraction(2,2,5), write(“2-2 равно 5”), nl, change(5, Ch), write(Ch). Модуль, связываемый с этой программой должен содержать процедуры: subtraction_0 (int x, int y, int *z) {*z=x-y;} subtraction_1 (int x, int *y, int z) {*y=x-z;} subtraction_2 (int *x, int y, int z) {*x=y-z;} subtraction_3 (int x, int y, int z) {if ((x-y)!=z)RUN_Fail();} change(int a, int *b) {*b=a;} Примечание: если процедура написана на языке C, то параметры заносятся в стек в обратном порядке (после возврата значений указатель автоматически корректируется VP), в противном случае, параметры заносятся в стек в нормальном порядке (см. таблицу 1). Форматы объектных файлов в Win32. Под Win32 используется 2 формата объектных файлов: OMF (объектно-модульный формат – используется, например, BorlandC++ ) и COFF (Общий объектно-файловый формат, используется, например, VisualC++ ). 1. При использовании файла в формате OMF имя предиката должно совпадать с именем функции. 2. При использовании файла в формате COFF, к имени предиката добавляется знак подчеркивания, и после символа @ указывается количество байт, добавленных в стек (например, если предикат nameимеет 2 целых аргумента, то он должен быть объявлен как _name@8 (см. таблицу 1)). Установка указателя на стек. Существует два способа установки указателя на стек: при объявлении функции и при ее вызове. Так сложилось, что Pascal устанавливает указатель при объявлении функции, а С – при вызове (см. таблицу 1).
Таблица 1: вызов модулей из VP. Неавтоматическое обозначение внешних предикатов. Идентификатор процедуры или функции в VP не обязательно должен совпадать с идентификатором во внешнем модуле. В этом случае объявление такого предиката имеет вид: GLOBAL PREDICATES add(integer, integer, integer) – (i,o) language c as “_myadd@12” Эквивалентность типов. Большинство простых типов переменных в VP имеют эквиваленты в других языках программирования, однако размер резервируемой для них памяти может не совпадать (см. таблицу 2).
Таблица 2: размер переменных в VP. Обработка списков. Ниже приведен пример программы, преобразующей список в массив, и затем вновь возвращающей данные в список. Программа ListToArray на языке С преобразует список целых чисел в массив, записывает в стек элементы массива и возвращает количество элементов (массив и количество элементов передаются в программу как параметры). Преобразование списка проходит в 2 этапа: 1. Просматривается список и находится количество элементов в нем. 2. Целые числа из списка заносятся в массив, состоящий из известного количества элементов. /* Program lstar_p.pro */ project "lstar" global domains ilist = integer* global predicates inclist(ilist,ilist) - (i,o) language c goal inclist([1,2,3,4,5,6,7],L), write(L). /* Program lstar_c.c */ #define listfno 1 #define nilfno 2 typedef unsigned char BYTE; void *MEM_AllocGStack(unsigned); typedef struct ilist { BYTE Functor; int Value; struct ilist *Next; } INTLIST; int ListToArray(INTLIST *List,int **ResultArray) { INTLIST *SaveList = List; int *Array, len; register int *ArrP; register int i; /* количество элементов в списке */ i = 0; while ( List->Functor == listfno ) { i++; List = List->Next; } len = i; Array = MEM_AllocGStack(i*sizeof(int)); ArrP = Array; /* перемещение элементов списка в массив */ List = SaveList; while ( i != 0 ) { *ArrP++ = List->Value; List = List->Next; i--; } *ResultArray = Array; return(len); } void ArrayToList(register int *ArrP,register int n, { while ( n != 0 ) { *ListPP = MEM_AllocGStack(sizeof(INTLIST)); (*ListPP)->Functor = listfno; (*ListPP)->Value = *ArrP++; ListPP = &(*ListPP)->Next; n--; } *ListPP = MEM_AllocGStack(sizeof((*ListPP)->Functor)); (*ListPP)->Functor = nilfno; } void inclist(INTLIST *InList,INTLIST **OutList) { register int *ArrP, i, len; int *Array; len = ListToArray(InList,&Array); ArrP = Array; for ( i = 0; i < len; i++) ++*ArrP++; ArrayToList(Array,len,OutList); } Вызов предикатов VP. VP способен не только вызывать предикаты, но и предоставлять их другим программам. Ниже приведен пример вызова предиката prowin_msg из программы на С: /* Program hello_p.pro */ global predicates char prowin_msg(string) - (i) language c hello_c - language c clauses prowin_msg(S,C) :- write(S," (press any key)"), readchar(C). goal prowin_msg("Hello from PDC Prolog"), hello_c. /* Program hello_c.c */ char prowin_msg(char *); void hello_c() { while ( prowin_msg("Hello from C (press 'C')") != 'C' ) ; } 2003 Pechenkin pechenkin@pochtamt.ru www.cs.vsu.ru/~pechenkin |