РефератыИнформатикаИсИспользование Prolog совместно с другими ЯП

Использование Prolog совместно с другими ЯП

Использование
Prolog совместно с другими ЯП.


Понятие
Dll.


Вспомним процесс программирования в DOS. Преобразование исходного текста в машинный код включал в себя 2 процесса: компиляцию и линковку. Во время линковки в код программы помещались не только объявления функций и процедур, но и их полный код.


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


рис 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).





r />





















Конвертирует имена в верхний регистр. Порядок аргументов прямой. Устанавливает указатель на стек при объявлении. Необходимость конвертировать имена в формат COFF.
C - - -
pascal + + +
stdcall + - +
syscall + + -

Таблица 1: вызов модулей из
VP.


Неавтоматическое обозначение внешних предикатов.


Идентификатор процедуры или функции в VP не обязательно должен совпадать с идентификатором во внешнем модуле. В этом случае объявление такого предиката имеет вид:


GLOBAL PREDICATES


add(integer, integer, integer) – (i,o) language c as “_myadd@12”


Эквивалентность типов.


Большинство простых типов переменных в VP имеют эквиваленты в других языках программирования, однако размер резервируемой для них памяти может не совпадать (см. таблицу 2).























Тип переменной Размер (Win32).
char, byte 1 байт
short, word 2 байт
long, dword 4 байт
unsigned, integer 4 байт
Real 8 байт
Ref 4 байт

Таблица 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, register INTLIST **ListPP)


{


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

Сохранить в соц. сетях:
Обсуждение:
comments powered by Disqus

Название реферата: Использование Prolog совместно с другими ЯП

Слов:1147
Символов:11203
Размер:21.88 Кб.