.

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

Язык: русский
Формат: реферат
Тип документа: Word Doc
73 407
Скачать документ

Использование 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
(объектно-модульный формат – используется, например, Borland C++ ) и
COFF (Общий объектно-файловый формат, используется, например, Visual C++
).

При использовании файла в формате OMF имя предиката должно совпадать с
именем функции.

При использовании файла в формате COFF, к имени предиката добавляется
знак подчеркивания, и после символа @ указывается количество байт,
добавленных в стек (например, если предикат name имеет 2 целых
аргумента, то он должен быть объявлен как _name@8 (см. таблицу 1)).

Установка указателя на стек.

Существует два способа установки указателя на стек: при объявлении
функции и при ее вызове. Так сложилось, что Pascal устанавливает
указатель при объявлении функции, а С – при вызове (см. таблицу 1).

Конвертирует имена в верхний регистр. Порядок аргументов прямой.
Устанавливает указатель на стек при объявлении. Необходимость
конвертировать имена в формат 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 этапа:

Просматривается список и находится количество элементов в нем.

Целые числа из списка заносятся в массив, состоящий из известного
количества элементов.

/* 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

Нашли опечатку? Выделите и нажмите CTRL+Enter

Похожие документы
Обсуждение

Ответить

Курсовые, Дипломы, Рефераты на заказ в кратчайшие сроки
Заказать реферат!
UkrReferat.com. Всі права захищені. 2000-2020