Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Написание игр _ P-robots

Автор: Altair 18.04.2004 17:37

Видели поединки P-роботов?
Если нет, советую посмотреть.
Так вот, это очень старая штука.
А что если сделать новую версию, только с более красочными боями?
Тогда можно было бы устраивать бои роботов.
Как идея?

Автор: SKVOZNJAK 19.04.2004 0:41

Это типа змеиных боёв?

Автор: Altair 19.04.2004 10:13

Да, только в существующих P-ROBOTS, деруться точки(на экране)! rolleyes.gif

Автор: EXE 25.04.2004 17:38

У тебя уже что-нибудь написано или все с нуля начинать надо?

Автор: Altair 25.04.2004 18:24

Все с нуля.
-----
А кто здесь боиться трудностей?

Автор: AlaRic 1.05.2004 10:39

Видимо много кто раз молчат! <_<

Автор: Altair 9.06.2004 19:40

Цитата
Видимо много кто раз молчат! 

К сожалению почти все.

Автор: APAL 9.06.2004 20:17

А что это за Р-Роботс? Где можно про них инфу почитать?

Автор: Altair 9.06.2004 23:11

http://pascal.sources.ru/gamestxt/probots4.htm

Автор: Romtek 9.06.2004 23:18

Цитата(EXE)
У тебя уже что-нибудь написано или все с нуля начинать надо?


Цитата(Oleg_Z)
Все с нуля


Зачем с нуля? Исходники то есть! (у меня, например) smile.gif

Автор: Altair 9.06.2004 23:26

Исходники есть, потому что я кинул ссылку, с которой можно скачать исходники.
Только там 2 проблеммы:
1. Разобраться в коде сложно.
2. Реализация там не очень хорошая. (плохая графика и т.д.)
-----------
Кстати на сурсах побобная идея у кого-то была.

Автор: Romtek 10.06.2004 0:00

На мой взгляд, легче будет всё таки разобраться в коде, т.к. написан неплохо.
А графику улучшить не проблема.

Автор: Altair 10.06.2004 1:41

Тоже верно.
Если я правильно понял тебя, romtek, то ты хочешь сказать: "Я готов улучшать P-ROBOTS". Так?

Автор: Romtek 10.06.2004 3:06

Цитата(Oleg_Z)
Если я правильно понял тебя, romtek, то ты хочешь сказать: "Я готов улучшать P-ROBOTS". Так?
Честное слово, я бы с радостью!
Но сессия не позволит sad.gif

Автор: Altair 10.06.2004 10:30

Я тоже сейчас занят.
Можно отложить это до лучших времен, идея модернизировать П-Роботов, мне очень нравится.

Автор: WiZarDX 10.06.2004 16:35

если проект будет продолжен, то я тоже не прочь к вам подключиться smile.gif
у меня тоже была когда-то такая идея, но токо с танками, а не с роботами, но я думаю с роботами веселее будет smile.gif

так что если что - меня не забывайте rolleyes.gif

Автор: Altair 10.06.2004 17:59

Можно и с танками.
Мы же не говорим, робот-андроид. Танк тоже может быть роботом!

Автор: WiZarDX 14.06.2004 16:09

согласен

у меня есть идея насчет роботов!
что если делать не готовые скомпилированные процдуры для управления роботов, а реализовать что-то наподобие скрипта (с синтаксисом паскаля)

я тут как раз начал скриптами заниматься (т.е. их разработкой), так что недели через 2 можа что и будет работать...

Автор: Romtek 14.06.2004 17:29

Цитата(WiZarDX)
что если делать не готовые скомпилированные процдуры для управления роботов, а реализовать что-то наподобие скрипта (с синтаксисом паскаля)
Идея хорошая! Я тоже об этом думал.

Автор: Altair 10.09.2004 22:52

В связи с некоторыми событиями, тема оживает, и набираются желающие.
Нам нужны:

1. программист графики
2. программист системник
3. компилятор*
4. художник
5. сценарист
Это не значит, что нам нужны специалисты, просто если хотите учавствовать, то определитесь кем вы будете

------------------
ПРИМЕЧАНИЕ:
* компилятор - человек, занимающийся компиляцией (словарь Ожегова)
компиляция - процесс сборки в единое целое чужих исследований, разработок (тоже из Ожегова)

Автор: BlackShadow 11.09.2004 20:42

Скинул бы как проект для команды. Всё равно простаивает эта затея...

Автор: Altair 11.09.2004 20:57

Так и есть!

Автор: FreeMan 14.09.2004 19:45

2. программист системник скорее всего.

Автор: WiZarDX 11.10.2004 13:02

1. grafix programmer

esli eto budet bez vsiakix tam OpenGL'ov i DirectX'ov.

Автор: GoodWind 11.10.2004 20:20

Цитата
esli eto budet bez vsiakix tam OpenGL'ov i DirectX'ov.

?? 320x200x 256 colors под dos

Автор: Guest 12.10.2004 11:45

nu pocemu,
mozno dojti i do 1024x768 32bit colors. s VESA rezimami. (LFB ili banked eto cto u kogo idet).
esli konecno takije rezimy u vas podderzivajuca...

opyt s programirovanijem VESA rezimov u menia est.

Автор: WiZarDX 12.10.2004 11:50

sorry, cto ne zaregistrirovalsia vnaciale...

razjasnite mne odnu vesh' - podo cto budet P-ROBOTS pisatsia? pod DOS?

PS. esli cto, to ja storonnik DOSa smile.gif

Автор: Altair 12.10.2004 12:21

Да, под ДОС.

Автор: WiZarDX 12.10.2004 12:33

togda otlicno smile.gif

esli nuzna budet grafika, to obrashiajtes ko mne.
zelatelno po mail'u, a to na forume ja ne ciasto byvaju, t.k. doma NETa netu...

(wizardx@mail15.com)

Автор: Prometeus 12.10.2004 17:00

А кто-нибудь писал непосредственно роботов под p-robots.
А то оказывается игрушка старючая а роботов в инете написаных кроме стандартных в пакете я не нашел. Вот написал робота который всех сделал хотел померяться с чужими.

ЗЫ. Мне такого рода прут игрушки. Не понимаю почему их так мало. Или если есть то тупые какие-то.

Автор: RL 27.11.2004 21:01

Дети, хватит париться над этими мелочами. ;) Пора бы перейти на 32-х разрядную графику с разрешением 800*600. И попробуйте делать проги > 10 мегов. lol.gif

Автор: Altair 27.11.2004 21:07

RL, между прочим, ребенок, тут никто 16 битными и не занимается.

Цитата
И попробуйте делать проги > 10 мегов. 

<_<
Плохо... слишком большой код, я уверен что его можно оптимизировать раза в полтора... чем меньше код, тем он надежнее.. windows доказала, что если весишь 200 МБ это не значит что конфетка.

Цитата
Пора бы перейти на 32-х разрядную графику с разрешением 800*600.

Нет, я сейчас занимаюсь DireсtX графикой...
1024*768 32 бита...
мое любимое разрешение.. такое было еще в старом добром ДОСе ...

Автор: Rl 27.11.2004 21:26

У меня около 500Kb занимает код... А остальное музыка, картинки и данные... :low:

Автор: Altair 27.11.2004 21:39

500 кб исходный текст кода или EXE?
если второе то не о чем не говорит, у меня 1,6 МБ не сжимая... (оптимизация по времени исполнения).

Автор: RL 28.11.2004 2:29

Исходный текст конечно. Но картинки в формате BMP. Если знаешь как можно читать в TMT Pascal JPEG поделись опытом, буду благодарен!

Автор: Altair 28.11.2004 2:35

Цитата
Если знаешь как можно читать в TMT Pascal JPEG поделись опытом, буду благодарен!

С удовольствием.
А именно: не занимайся бредом, качай библиотеку GraphiX:

http://stud3.tuwien.ac.at/%7Ee9826443/graphix/gxframe.html


она под FPC вообще-то, но и под TMT вроде пашет, так вот, она поддерживает куча граф. и медиа файлов.

Зачем изобретать велосипед, если он есть?


Цитата
GraphiX is a Graphics Library for Freepascal running under DOS, Windows and Linux
It is designed to provide an easy and fast access to various graphics modes
Resolutions from 320x200 upto 1600x1200 and higher at colordepths 8,15,16,24 and 32bits are supported
many drawing primitives - pixels, lines, bars, rectangles, circles, polygonens, ...
mouse-library - colored and size unlimited mouse pointers
image-handling-library - loading BMP, GIF, ICO, JPG, PCX, PBM/PGM/PPM, PNG, TGA, TIF - saving BMP, PPM, TGA
font-library - it supports FNT-bitmap-fonts, CHR-BGI-fonts, VGA-BIOS 16x8 font and Truetype-Fonts
graphics-effects-library - alphablending, saturated add/sub, masking operations, rotating, scaling, ...
triangle-output-library - it can be used for 3D things -flat, gouraud-shaded and textured triangles)
video & animation-library - AVI, FLI/FLC, GIF and MOV (Quicktime)

В крйнем случае, компильши на FPC и затем что надо в DLL пихаешь ...

Автор: RL 28.11.2004 11:48

Спасибо за ссылку! :D
Но не все мне подходит. У меня TMT Pascal 3.90 Lite.
Модулей message.fpd, windows.fpd и др. нет, поэтому я не могу пользоваться DirectX. sad.gif

Автор: GoodWind 28.11.2004 12:06

Цитата
не все мне подходит. У меня TMT Pascal 3.90 Lite.
Модулей message.fpd, windows.fpd и др. нет, поэтому я не могу пользоваться DirectX.

тот же трабл sad.gif

Автор: Altair 28.11.2004 12:17

А чем не устраивает Free Pascal?
Можно на нем части кода писать и портировать в динамический библиотеки например....

Автор: RL 29.11.2004 3:18

Качать с инета очень долго, ведь он весит около 16 мегов. sad.gif

Автор: Guest 29.11.2004 3:20

Разве Free Pascal позволяет работать под Windows и с DirectX? huh.gif

Автор: GoodWind 29.11.2004 4:42

Цитата
Разве Free Pascal позволяет работать под Windows и с DirectX?

кхы... посмотрите подменю compile->target

Автор: Altair 29.11.2004 10:48

Цитата
Разве Free Pascal позволяет работать под Windows и с DirectX? 

ха-ха-ха lol.gif

А что нет?


Или вы увидели консольный режим IDE с псевдографикой, и решили что это ДОС? smile.gif

Автор: RL 7.12.2004 19:19

охота воспроизвести MP3 в TMT Pascal. Может кто-нибудь указать ссылку где это найти?

Автор: Probel 15.11.2005 23:36

Цитата(Altair @ 28.11.2004 9:17)
А чем не устраивает Free Pascal?
Можно на нем части кода писать и  портировать в динамический библиотеки например....

ты имеешь в виду, что можно запихнуть части grafix'а в dll а потом из TMT работать с ними?=) а можно по-подробнее плизз rolleyes.gif

Автор: Altair 15.11.2005 23:41

Цитата
ты имеешь в виду, что можно запихнуть части grafix'а в dll а потом из TMT работать с ними?=)

мммм.. ну можно конечно...
MeD что-то пробовал ...
а что подробнее?
пишем DLL в которой исползуем все что надо из графикса..
напрмер INITGRAPh; процедура будет инициализировать граф. режим, а в описании используемм графикс и загружаем какие надо режимы...

Автор: Probel 15.11.2005 23:54

мне б надо в TMT использовать все или почти все из графикса... а именно:
открытие всяких графических фалов (главное это BMP и JPEG), запуск всех видеорижимов графикса(если вдруг стандартные тмтэшные не захотят работать с графическими файлами)
как бы это сделать?
я вообще не умею dll делать и никогда с ними не работал

Автор: Altair 16.11.2005 0:02

думаю поймешь что я имею ввиду..

library MyDLL; 
uses
Windows, Graphix, GxIMG {....} ;

procedure OutBMP(filename:string; x0,y0:integer);
begin
{имея filename, x0,y0 - выводим что надо}
end;

exports
OutBMP;

begin
end.


Цитата
я вообще не умею dll делать и никогда с ними не работал

ну так прочти про них...

Автор: Probel 16.11.2005 0:07

Цитата(Altair @ 15.11.2005 21:02)
думаю поймешь что я имею ввиду..
library MyDLL; 
uses
Windows, Graphix, GxIMG {....} ;

procedure OutBMP(filename:string; x0,y0:integer);
begin
{имея filename, x0,y0 - выводим что надо}
end;

exports
OutBMP;

begin
end.


спасибо
Цитата
ну так прочти про них...

а у нас тут где-нить на форуме про это расказывается, или надо ковыряться во всем инэте такую инфу?...

Автор: Altair 16.11.2005 0:25

вот тебе из DRKB:

Цитата
Если ваш компьютер работает под управлением операционной системы Windows, то вы не можете не знать о существовании динамических подсоединяемых библиотек (dynamic link libraries - DLL). Достаточно взглянуть на список файлов, расположенных в системном каталоге Windows - порой количество используемых операционной системой динамических библиотек достигает нескольких сотен. DLL являются неотъемлемой частью функционирования операционных систем семейства Microsoft Windows. Однако для вас может быть неочевидна необходимость использования динамических библиотек при разработке приложений. В рамках данной статьи мы поговорим о принципах функционирования DLL и их использования в процессе создания ваших собственных программ.

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

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

Итак, процедуры и функции, содержащиеся в динамической библиотеке, можно разделить на два типа: те, которые могут быть вызваны из других приложений. Рассмотрим следующий пример:

Screen.Cursors[myCursor] := LoadCursor(HInstance, MYCURSOR');

LoadCursor - функция Windows API, которая вызывается приложением из динамической библиотеки User 32.dll. Кстати, примером хранимых в динамической библиотеке ресурсов могут являться такие стандартные диалоги Windows, как диалог открытия файла, диалог печати или настройки принтера. Эти диалоги находятся в файле Comctl32.dll. Однако многие прикладные разработчики используют функции вызова форм этих диалогов, совершенно не задумываясь, где хранится их описание.

Второй тип процедур - это те, которые используются только внутри самого файла библиотеки.


Аргументы в пользу использования DLL



Итак, прежде чем перейти к обсуждению структуры динамических библиотек, необходимо поговорить о тех преимуществах, которые предоставляет их использование разработчику. Во-первых, это повторное использование кода. Думаю, нет необходимости пояснять удобство использования один раз разработанных процедур и функций при создании нескольких приложений? Кроме того, в дальнейшем вы сможете продать некоторые из своих библиотек, не раскрывая исходных кодов. А чем тогда это лучше компонентов, спросите вы? А тем, что функции, хранящиеся в библиотеке, могут быть вызваны на выполнение из приложений, разработанных не на Object Pascal, а, например, с использованием C++Builder, Visual Basic, Visual C++ и т.д. Такой подход накладывает некоторые ограничения на принцип разработки библиотеки, но это возможно. Звучит заманчиво? Мне кажется, даже очень. Но это еще не все.

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

В-третьих, следует поговорить вот о чем. Всего несколько лет назад при разработке программного обеспечения вы могли совершенно не волноваться относительно распространения ваших продуктов где-либо, кроме вашей страны. Я хочу сказать, что проблема перевода на другие языки текста на элементах управления (пункты меню, кнопки, выпадающие списки, подсказки), сообщений об ошибках и т.д. не стояла так остро, как сейчас. Однако, с повсеместным внедрением интернета у вас появилась возможность быстрой передачи готовых программных продуктов практически в любую точку мира. И что будут делать с вашей программой где-нибудь в Объединенных Арабских Эмиратах, если кроме как по-русски, она с пользователем общаться не умеет? Вы сами можете оценить этот эффект, если хоть раз на экране вашего компьютера вместо с детства знакомого русского языка появляется "арабская вязь" (например, из-за "сбоя" шрифтов). Итак, уже сейчас вы должны планировать возможность распространения ваших приложений в других странах (если, конечно, у вас есть желание получить как можно больше прибыли). Соответственно, встает вопрос быстрого перевода интерфейса вашей программы на другие языки. Одним из путей может являться создание ресурсов интерфейсов внутри DLL. К примеру, можно создать одно приложение, которое в зависимости от версии динамической библиотеки будет выводить сообщения на различных языках.

Естественно, выше приведены лишь некоторые из аргументов в пользу использования динамически подключаемых библиотек при разработке приложений. Итак, надеюсь, вы все еще заинтересованы в том, чтобы узнать, как, собственно, DLL создаются. Если так, то вперед.


Основы разработки DLL



Разработка динамических библиотек не представляет собой некий сверхсложный процесс, доступный лишь избранным. Если вы достаточно хорошо знакомы с разработкой приложений на Object Pascal, то вам не составит особого труда научиться работать с механизмом DLL. Итак, рассмотрим те особенности создания DLL, которые вам необходимо знать, а в завершении статьи разработаем свою собственную библиотеку.

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

library MyFirstDLL;
uses
  SysUtils, Classes, Forms, Windows;

procedure HelloWorld(AForm : TForm);
begin
  MessageBox(AForm.Handle, 'Hello world!', 'DLL Message Box',
  MB_OK or MB_ICONEXCLAMATION);
end;

exports
  HelloWorld;

begin
end.

Первое, на что следует обратить внимание, это ключевое слово library, находящееся вверху страницы. Library определяет этот модуль как модуль библиотеки DLL. Далее идет название библиотеки. В нашем примере мы имеем дело с динамической библиотекой, содержащей единственную процедуру: HelloWorld. Причем обратите внимание, что данная процедура по структуре ничем не отличается от тех, которые вы помещаете в модули своих приложений. Ключевое слово exports сигнализирует компилятору о том, что перечисленные ниже функции и/или процедуры должны быть доступны из вызывающих приложений (т.е. они как бы "экспортируются" из библиотеки). Подробнее о механизме экспорта мы поговорим чуть позже.

И, наконец, в конце модуля можно увидеть ключевые слова begin и end. Внутри данного блока вы можете поместить код, который должен выполняться в процессе загрузки библиотеки. Достаточно часто этот блок остается пустым.

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

Описание и реализация процедур и функций, вызываемых в пределах текущей DLL, ничем не отличаются от их аналогов в обычных проектах-приложениях. Их специфика заключается лишь в том, что вызывающая программа не будет иметь к ним доступа. Она просто не будет ничего знать об их существования, так же, как одни классы ничего не знают о тех методах, которые описаны в секции private других классов.

В дополнение к процедурам и функциям, DLL может содержать глобальные данные, доступ к которым разрешен для всех процедур и функций в библиотеке. Для 16-битных приложений эти данные существовали в единственном экземпляре независимо от количества загруженных в оперативную память программ, которые используют текущую библиотеку. Другими словами, если одна программа изменяет значение глобальной переменной a на 100, то для всех остальных приложений a будет значение 100. Для 32-битных приложений это не так. Теперь для каждого приложения создается отдельная копия глобальной области данных.




Автор: Altair 16.11.2005 0:26

Цитата
Экспорт функций из DLL



Как уже говорилось выше, для экспорта процедур и функций из DLL, необходимо использовать ключевое слово export. Еще раз обратите внимание на представленный выше листинг библиотеки MiFirstDll. Поскольку процедура HelloWorld определена как экспортируемая, то она может быть вызвана на выполнение из других библиотек или приложений. Существуют следующие способы экспорта процедур и функций: экспорт по имени и экспорт по порядковому номеру.

Наиболее распространенный способ экспорта - по имени. Взглянем на приведенный ниже текст:

exports
  SayHello,
  DoSomething,
  DoSomethingReallyCool;

Следует обратить внимание на то, что Delphi автоматически назначает порядковый номер каждой экспортируемой функции (процедуре) независимо от того, определяете вы его явно или нет. Явное определение индекса позволяет вам лично управлять порядковым номером экспортируемой функции или процедуры.

Для того, чтобы определить выполняется ли ваш кодек в DLL или в вызывающем приложении, можно воспользоваться глобальной переменной IsLibrary. Она принимает значение true в том случае, если код вызывается из библиотеки и false в случае выполнения процедуры или функции из вызывающего приложения.

Кроме этого, в поставку Delphi входит весьма полезная утилита tdump, которая предоставляет данные о том, какая информация экспортируется из указанной DLL.


Использование DLLProc



Выше я уже говорил о том, что код инициализации динамической библиотеки может быть помещен в блок begin...end. Однако кроме этого зачастую необходимо предусмотреть некоторые действия, выполняемые в процессе выгрузки DLL из оперативной памяти. В отличии от других типов модулей, модуль DLL не имеет ни секции initialization, ни секции finalization. К примеру, вы можете динамически выделить память в главном блоке, однако не понятно, где эта память должна быть освобождена. Для решения этой проблемы существует DLLProc - специальная процедура, вызываемая в определенные моменты функционирования DLL.

Для начала следует сказать о самой причине существования DLLProc. Динамическая библиотека получает сообщения от Windows в моменты своей загрузки и выгрузки из оперативной памяти, а также в тех случаях, когда какой-нибудь очередной процесс, использующий функции и/или ресурсы, хранящиеся в библиотеке, загружается в память. Такая ситуация возможно в том случае, когда библиотека необходима для функционирования нескольких приложений. А для того, чтобы вы имели возможность указывать, что именно должно происходить в такие моменты, необходимо описать специальную процедуру, которая и будет ответственна за такие действия. К примеру, она может выглядеть следующим образом:

procedure MyFirstDLLProc(Reason: Integer);
begin
  if Reason = DLL_PROCESS_DETACH then
    {DLL is unloading. Cleanup code here.}
end;

Однако системе совершенно не очевидно, что именно процедура MyFirstDllProc ответственна за обработку рассмотренных выше ситуаций. Поэтому вы должны поставить в соответствие адрес нашей процедуры глобальной переменной DLLProc. Это необходимо сделать в блоке begin...end примерно так:

begin
  DLLProc := @MyDLLProc;
  { Что-нибудь еще, что должно выполняться в
  процессе инициализации библиотеки }
end.

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

library MyFirstDLL;
uses
  SysUtils, Classes, Forms, Windows;

var
  SomeBuffer: Pointer;

procedure MyFirstDLLProc(Reason: Integer);
begin
  if Reason = DLL_PROCESS_DETACH then
    {DLL is выгружается из памяти.
    Освобождаем память, выделенную под буфер.}
    FreeMem(SomeBuffer);
end;

procedure HelloWorld(AForm: TForm);
begin
  MessageBox(AForm.Handle, 'Hello world!',
  'DLL Message Box', MB_OK or MB_ICONEXCLAMATION);
end;

{Какой-нибудь код, в котором используется SomeBuffer.}

exports
  HelloWorld;

begin
  {Ставим в соответствие переменной
  DLLProc адрес нашей процедуры.}
  DLLProc := @MyFirstDLLProc;
  SomeBuffer := AllocMem(1024);
end.

Как можно увидеть, в качестве признака того или иного события, в результате которого вызывается процедура MyFirstDll, является значение переменной Reason. Ниже приведены возможные значения этой переменной.

DLL_PROCESS_DETACH
библиотека выгружается из памяти; используется один раз;
DLL_THREAD_ATTACH
в оперативную память загружается новый процесс, использующий ресурсы и/или код из данной библиотеки;
DLL_THREAD_DETACH
один из процессов, использующих библиотеку, "выгружается" из памяти.



Автор: Altair 16.11.2005 0:26

Цитата
Загрузка DLL



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

Статическая загрузка означает, что динамическая библиотека загружается автоматически при запуске на выполнение использующего ее приложения. Для того чтобы использовать такой способ загрузки, вам необходимо воспользоваться ключевым словом external при описании экспортируемой из динамической библиотеки функции или процедуры. DLL автоматически загружается при старте программы, и Вы сможете использовать любые экспортируемые из нее подпрограммы точно так же, как если бы они были описаны внутри модулей приложения. Это наиболее легкий способ использования кода, помещенного в DLL. Недостаток метода заключается в том, что если файл библиотеки, на который имеется ссылка в приложении, отсутствует, программа откажется загружаться.

Смысл динамического метода заключается в том, что вы загружаете библиотеку не при старте приложения, а в тот момент, когда вам это действительно необходимо. Сами посудите, ведь если функция, описанная в динамической библиотеке, используется только при 10% запусков программы, то совершенно нет смысла использовать статический метод загрузки. Выгрузка библиотеки из памяти в данном случае также осуществляется под вашим контролем. Еще одно преимущества такого способа загрузки DLL - это уменьшение (по понятным причинам) времени старта вашего приложения. А какие же у этого способа имеются недостатки? Основной, как мне кажется, - это то, что использование данного метода является более хлопотным, чем рассмотренная выше статическая загрузка. Сначала вам необходимо воспользоваться функцией Windows API LoadLibrary. Для получения указателя на экспортируемой процедуры или функции должна использоваться функция GetProcAddress. После завершения использования библиотеки DLL должна быть выгружена с применением FreeLibrary.


Вызов процедур и функций, загруженных из DLL.



Способ вызова процедур и функций зависит от того, каким образом вы загрузили динамическую библиотеку, в которой эти подпрограммы находятся.

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

procedure SayHello(AForm : TForm); external myfirstdll.dll';

Ключевое слово external сообщает компилятору, что данная процедура может быть найдена в динамической библиотеке (в нашем случае - myfirstdll.dll). Далее вызов этой процедуры выглядит следующим образом:

...
HelloWorld(self);
...

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

Импорт из DLL может проводиться по имени процедуры (функции), порядковому номеру или с присвоением другого имени.

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

procedure HelloWorld(AForm : TForm);external myfirstdll.dll' index 15;


В этом случае имя, которое вы даете процедуре при импорте не обязательно должно совпадать с тем, которое было указано для нее в самой DLL. Т.е. приведенная выше запись означает, что вы импортируете из динамической библиотеки myfirstdll.dll процедуру, которая в ней экспортировалась пятнадцатой, и при этом в рамках вашего приложения этой процедуре дается имя SayHello.

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

procedure CoolProcedure;external myfirstdll.dll' name DoSomethingReallyCool';

Здесь импортируемой процедуре CoolProcedure дается имя DoSomethingReallyCool. Вызов процедур и функций, импортируемых из динамически загружаемых библиотек несколько более сложен, чем рассмотренный нами выше способ. В данном случае требуется объявить указатель на функцию или процедуру, которую вы собираетесь использовать. Помните процедуру HelloWorld? Давайте посмотрим, что необходимо сделать для того, чтобы вызвать ее на выполнение в случае динамической загрузки DLL. Во-первых, вам необходимо объявить тип, который описывал бы эту процедуру:

type
  THelloWorld = procedure(AForm : TForm);

Теперь вы должны загрузить динамическую библиотеку, с помощью GetProcAddress получить указатель на процедуру, вызвать эту процедуру на выполнение, и, наконец, выгрузить DLL из памяти. Ниже приведен код, демонстрирующий, как это можно сделать:

var
  DLLInstance : THandle;
  HelloWorld : THelloWorld;
begin
  { загружаем DLL }
  DLLInstance := LoadLibrary(myfirstdll.dll');
  { получаем указатель }
  @HelloWorld := GetProcAddress(DLLInstance, HelloWorld');
  { вызываем процедуру на выполнение }
  HelloWorld(Self);
  { выгружаем DLL из оперативной памяти }
  FreeLibrary(DLLInstance);
end;

Как уже говорилось выше, одним из недостатков статической загрузки DLL является невозможность продолжения работы приложения при отсутствии одной или нескольких библиотек. В случае с динамической загрузкой у вас появляется возможность программно обрабатывать такие ситуации и не допускать, чтобы программа "вываливалась" самостоятельно. По возвращаемому функциями LoadLibrary и GetProcAddress значениям можно определить, успешно ли прошла загрузка библиотеки и найдена ли в ней необходимая приложению процедура. Приведенный ниже код демонстрирует это.

procedure TForm1.DynamicLoadBtnClick(Sender: TObject);
type
  THelloWorld = procedure(AForm : TForm);
var
  DLLInstance : THandle;
  HelloWorld : THelloWorld;
begin
  DLLInstance := LoadLibrary('myfirstdll.dll');
  if DLLInstance = 0 then
  begin
    MessageDlg('Невозможно загрузить DLL', mtError, [mbOK], 0);
    Exit;
  end;
  @HelloWorld := GetProcAddress(DLLInstance, 'HelloWorld');
  if @HelloWorld <> nil then
    HelloWorld (Self)
  else
    MessageDlg('Не найдена искомая процедура!.', mtError, [mbOK], 0);
  FreeLibrary(DLLInstance);
end;


В DLL можно хранить не только код, но и формы. Причем создание и помещение форм в динамическую библиотеку не слишком сильно отличается от работы с формами в обычном проекте. Сначала мы рассмотрим, каким образом можно написать библиотеку, содержащую формы, а затем мы поговорим об использовании технологии MDI в DLL.

Разработку DLL, содержащую форму, я продемонстрирую на примере.

Итак, во-первых, создадим новый проект динамической библиотеки. Для этого выберем пункт меню File|New, а затем дважды щелкнем на иконку DLL. После этого вы увидите примерно следующий код:

library Project2;
{здесь были комментарии}
uses
  SysUtils, Classes;
{$R *.RES}
begin
end.

Сохраните полученный проект. Назовем его DllForms.dpr.

Теперь следует создать новую форму. Это можно сделать по-разному. Например, выбрав пункт меню File|New Form. Добавьте на форму какие-нибудь компоненты. Назовем форму DllForm и сохраним получившийся модуль под именем DllFormUnit.pas.

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

function ShowForm : Integer; stdcall;
var
  Form : TDLLForm;
begin
  Form := TDLLForm.Create(Application);
  Result := Form.ShowModal;
  Form.Free;
end;

Обращаю внимание, что для того, чтобы проект был скомпилирован без ошибок, необходимо добавить в секцию uses модуль Forms.

Экспортируем нашу функцию с использованием ключевого слова exports :

exports
  ShowForm;

Компилируем проект и получаем файл dllforms.dll. Эти простые шаги - все, что необходимо сделать для создания динамической библиотеки, содержащей форму. Обратите внимание, что функция ShowForm объявлена с использованием ключевого слова stdcall. Оно сигнализирует компилятору использовать при экспорте функции соглашение по стандартному вызову (standard call calling convention). Экспорт функции таким образом создает возможность использования разработанной DLL не только в приложениях, созданных в Delphi.

Соглашение по вызову (Calling conventions) определяет, каким образом передаются аргументы при вызове функции. Существует пять основных соглашений: stdcall, cdecl, pascal, register и safecall. Подробнее об этом можно узнать, посмотрев раздел "Calling Conventions" в файле помощи Delphi.

Также обратите внимание, что значение, возвращаемое функцией ShowForm, соответствует значению ShowModal. Таким образом вы можете передавать некоторую информацию о состоянии формы вызывающему приложению.

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

library DllForms;

uses
  SysUtils, Classes, Forms,
  DllFormUnit in 'DllFormUnit.pas' {DllForm};

{$R *.RES}

function ShowForm : Integer; stdcall;
var
  Form : TDLLForm;
begin
  Form := TDLLForm.Create(Application);
  Result := Form.ShowModal;
  Form.Free;
end;

begin
end.

 



unit TestAppUnit;
interface

uses
  Windows, Messages, SysUtils, Classes, Graphics,
  Controls, Forms, Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
end;

var
  Form1: TForm1;
  function ShowForm : Integer; stdcall; external 'dllforms.dll';

implementation
{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowForm;
end;

end.




Прошу заметить, что при экспорте функции также было использовано ключевое слово stdcall.

Следует обратить особое внимание на работу с дочерними формами в DLL. Если, к примеру, в вызывающем приложении главная форма имеет значение свойства FormStyle, равным MDIForm, то при попытке вызова из DLL MDIChild-формы, на экране появится сообщение об ошибке, в котором будет говориться, что нет ни одной активной MDI-формы.

В тот момент, когда вы пытаетесь показать ваше дочернее окно, VCL проверяет корректность свойства FormStyle главной формы приложения. Однако в нашем случае все вроде бы верно. Так в чем же дело? Проблема в том, что при проведении такой проверки, рассматривается объект Application, принадлежащий не вызывающему приложению, а собственно динамической библиотеке. Ну, и естественно, поскольку в DLL нет главной формы, проверка выдает ошибку. Для того чтобы избежать такой ситуации, надо назначить объекту Application динамической библиотеки объект Application вызывающего приложения. Естественно, это заработает только в том случае, когда вызывающая программа - VCL-приложение. Кроме того, перед выгрузкой библиотеки из памяти необходимо вернуть значение объекта Application библиотеки в первоначальное состояние. Это позволит менеджеру памяти очистить оперативную память, занимаемую библиотекой. Следовательно, вам нужно сохранить указатель на "родной" для библиотеки объект Application в глобальной переменной, которая может быть использована при восстановлении его значения.

Итак, вернемся немного назад и перечислим шаги, необходимые нам для работы с помещенным в DLL MDIChild-формами.

В динамической библиотеке создаем глобальную переменную типа TApplication.
Сохраняем указатель на объект Application DLL в глобальной переменной.
Объекту Application динамической библиотеки ставим в соответствие указатель на Application вызывающего приложения.
Создаем MDIChild-форму и работаем с ней.
Возвращаем в первоначальное состояние значение объекта Application динамической библиотеки и выгружаем DLL из памяти.
Первый шаг прост. Просто помещаем следующий код в верхней части модуля DLL:



var
  DllApp: TApplication;




Затем создаем процедуру, которая будет изменять значение объекта Application и создавать дочернюю форму. Процедура может выглядеть примерно так:



procedure ShowMDIChild(MainApp: TApplication);
var
  Child: TMDIChild;
begin
  if not Assigned(DllApp) then
  begin
    DllApp := Application;
    Application := MainApp;
  end;
  Child := TMDIChild.Create(Application.MainForm);
  Child.Show;
end;




Все, что нам теперь необходимо сделать, - это предусмотреть возвращение значения объекта Application в исходное состояние. Делаем это с помощью процедуры MyDllProc:



procedure MyDLLProc(Reason: Integer);
begin
  if Reason = DLL_PROCESS_DETACH then
    { DLL is выгружается. Восстанавливаем значение указателя Application}
    if Assigned(DllApp) then
      Application := DllApp;
end;





Вместо заключения



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


   
Взято с http://delphiworld.narod.ru

Автор: Probel 16.11.2005 1:29

Altair, спасибки! smile.gif

Автор: Altair 16.11.2005 1:41

Пожалуйста!
Скачай http://drkb.ru/ не пожалеешь! good.gif

Автор: Probel 16.11.2005 1:57

Цитата(Altair @ 15.11.2005 22:41)
Пожалуйста!
Скачай http://drkb.ru/ не пожалеешь!  good.gif

да, действительно классная вещь, спасибки за это тоже!.. 10 мб инфы... good.gif

Автор: GoodWind 16.11.2005 12:28

хм... портировать grafix по TMT что-ль.... а то извратом занимаетесь...

Автор: Probel 16.11.2005 20:57

Цитата(GoodWind @ 16.11.2005 9:28)
хм... портировать grafix по TMT что-ль.... а то извратом занимаетесь...

GoodWind, давай, портируй, я рад буду smile.gif

Автор: volvo 16.11.2005 21:36

Цитата
хм... портировать grafix по TMT что-ль....

Угу... Ты его лучше под FPC 2.0.0 сначала спортируй...

Автор: Altair 17.11.2005 0:23

Цитата
Ты его лучше под FPC 2.0.0 сначала спортируй...

ставлю кефир что у него ничего не выйдет... уже пытался smile.gif
http://freepascal.ru/forum/index.php?showtopic=13

Автор: arhimag 17.11.2005 1:55

Люди а выставьте пожалуйста исходник первой версии. По жалуйста!

Автор: Altair 17.11.2005 2:00

Цитата
исходник первой версии

первой версии чего ???
Графикса ? на сайте ищи и на форуме в разделе 32 бита есть

Автор: arhimag 17.11.2005 2:02

Нет, п роботс!!

Автор: Altair 17.11.2005 2:28

http://pascal.sources.ru/gamestxt/probots4.htm

Автор: Probel 17.11.2005 2:37

Цитата(volvo @ 16.11.2005 18:36)
Угу... Ты его лучше под FPC 2.0.0 сначала спортируй...

Цитата(Altair @ 16.11.2005 21:23)
ставлю кефир что у него ничего не выйдет... уже пытался smile.gif
http://freepascal.ru/forum/index.php?showtopic=13

а под TMT то можно
пробовал кто-нить?

Автор: Altair 17.11.2005 2:51

Цитата
а под TMT то можно

сомневаюсь... если не получилось под тот же компилер другой версии то врядл ли выйдет под другой диалект...

Автор: Probel 20.11.2005 22:37

Цитата(Altair @ 16.11.2005 23:51)
сомневаюсь... если не получилось под тот же компилер другой версии то врядл ли выйдет под другой диалект...

эхх, мне б хотя бы чтоб jpeg загружать в tmt... может кто-нить попробует все-таки? rolleyes.gif

Автор: GoodWind 21.11.2005 10:48

FFC не пользую =)) портировать не буду...
закончу с курсовой+практикой и портирую =)))) blum.gif

Автор: Gothic_Snake 23.12.2005 3:46

Цитата(Altair @ 10.09.2004 21:52) *

В связи с некоторыми событиями, тема оживает, и набираются желающие.
Нам нужны:

1. программист графики
2. программист системник
3. компилятор*
4. художник
5. сценарист
Это не значит, что нам нужны специалисты, просто если хотите учавствовать, то определитесь кем вы будете

------------------
ПРИМЕЧАНИЕ:
* компилятор - человек, занимающийся компиляцией (словарь Ожегова)
компиляция - процесс сборки в единое целое чужих исследований, разработок (тоже из Ожегова)

Вопрос: На каком языке писать собираетесь?

Автор: GoodWind 23.12.2005 3:51

lol.gif lol.gif lol.gif lol.gif
дату последнего поста смотри lol.gif
ну ты некрофил =)

Автор: Gothic_Snake 23.12.2005 22:00

Цитата(GoodWind @ 23.12.2005 2:51) *

lol.gif lol.gif lol.gif lol.gif
дату последнего поста смотри lol.gif
ну ты некрофил =)

Ну лан, чуть промазал...
Вообщем у нас тож еть такая идея... Игра на подобие Colobot. Вообщем идея та-же управление роботами по принципу скриптов (вся концепция ИИ будет выполнена так-же)...

На паскале это писать не оч. уж и удобно (графика на DirectX. Не удобство с описанием макросов, скорость работы чуть медленнее, работа с динамической памятью немного отличается, да и размер программы увеличится. Вообщем придется c++ изучать. Но в принципе здесь самое главное алгоритм, а не реализация.).
А вот концепцию скриптового языка мона писать уже на языке Pascal/c++/Java/Basic
Причем делать выбор языка скриптов опционально..

Сегодня уже главного перса придумали.... smile.gif

Автор: virt 24.12.2005 22:14

Ты ссылку дай куда выкладываете наработки.

Автор: arhimag 24.12.2005 22:38

Я бы 3 или 4 рад быбыл поучаствовать smile.gif))

Автор: Gothic_Snake 25.12.2005 17:56

Цитата(virt @ 24.12.2005 21:14) *

Ты ссылку дай куда выкладываете наработки.

В скоре сайтом займусь. Сейчас некода. Сессия, праздники, да и заболел я =(

Автор: Gothic_Snake 25.12.2005 18:30

Кстати, почему у меня не запускается проботс???