IPB
ЛогинПароль:

> P-robots, а почему бы не придумать что то лучше
сообщение
Сообщение #1


Ищущий истину
******

Группа: Пользователи
Сообщений: 4 825
Пол: Мужской
Реальное имя: Олег

Репутация: -  45  +


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


--------------------
Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов
сообщение
Сообщение #2


Ищущий истину
******

Группа: Пользователи
Сообщений: 4 825
Пол: Мужской
Реальное имя: Олег

Репутация: -  45  +


Цитата
Загрузка 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


--------------------
Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

Сообщений в этой теме
Altair   P-robots   18.04.2004 17:37
SKVOZNJAK   Это типа змеиных боёв?   19.04.2004 0:41
Altair   Да, только в существующих P-ROBOTS, деруться точки…   19.04.2004 10:13
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   http://pascal.sources.ru/gamestxt/probots4.htm   9.06.2004 23:11
Romtek   У тебя уже что-нибудь написано или все с нуля начи…   9.06.2004 23:18
Altair   Исходники есть, потому что я кинул ссылку, с котор…   9.06.2004 23:26
Romtek   На мой взгляд, легче будет всё таки разобраться в …   10.06.2004 0:00
Altair   Тоже верно. Если я правильно понял тебя, romtek, …   10.06.2004 1:41
Romtek   Если я правильно понял тебя, romtek, то ты хочешь …   10.06.2004 3:06
Altair   Я тоже сейчас занят. Можно отложить это до лучших …   10.06.2004 10:30
WiZarDX   если проект будет продолжен, то я тоже не прочь к …   10.06.2004 16:35
Altair   Можно и с танками. Мы же не говорим, робот-андроид…   10.06.2004 17:59
WiZarDX   согласен у меня есть идея насчет роботов! что…   14.06.2004 16:09
Romtek   что если делать не готовые скомпилированные процду…   14.06.2004 17:29
Altair   В связи с некоторыми событиями, тема оживает, и на…   10.09.2004 22:52
Gothic_Snake   В связи с некоторыми событиями, тема оживает, и н…   23.12.2005 3:46
BlackShadow   Скинул бы как проект для команды. Всё равно проста…   11.09.2004 20:42
Altair   Так и есть!   11.09.2004 20:57
FreeMan   2. программист системник скорее всего.   14.09.2004 19:45
WiZarDX   1. grafix programmer esli eto budet bez vsiakix t…   11.10.2004 13:02
GoodWind   ?? 320x200x 256 colors под dos   11.10.2004 20:20
Guest   nu pocemu, mozno dojti i do 1024x768 32bit colors.…   12.10.2004 11:45
WiZarDX   sorry, cto ne zaregistrirovalsia vnaciale... razj…   12.10.2004 11:50
Altair   Да, под ДОС.   12.10.2004 12:21
WiZarDX   togda otlicno :) esli nuzna budet grafika, to obr…   12.10.2004 12:33
Prometeus   А кто-нибудь писал непосредственно роботов под p-r…   12.10.2004 17:00
RL   Дети, хватит париться над этими мелочами. ;) По…   27.11.2004 21:01
Altair   RL, между прочим, ребенок, тут никто 16 битными и…   27.11.2004 21:07
Rl   У меня около 500Kb занимает код... А остальное муз…   27.11.2004 21:26
Altair   500 кб исходный текст кода или EXE? если второе т…   27.11.2004 21:39
RL   Исходный текст конечно. Но картинки в формате BMP.…   28.11.2004 2:29
Altair   С удовольствием. А именно: не занимайся бредом, к…   28.11.2004 2:35
RL   Спасибо за ссылку! :D Но не все мне подходит…   28.11.2004 11:48
GoodWind   тот же трабл :(   28.11.2004 12:06
Altair   А чем не устраивает Free Pascal? Можно на нем част…   28.11.2004 12:17
RL   Качать с инета очень долго, ведь он весит около 16…   29.11.2004 3:18
Guest   Разве Free Pascal позволяет работать под Windows и…   29.11.2004 3:20
GoodWind   кхы... посмотрите подменю compile->target   29.11.2004 4:42
Altair   ха-ха-ха :lol: А что нет? Или вы увидели кон…   29.11.2004 10:48
RL   охота воспроизвести MP3 в TMT Pascal. Может кто-ни…   7.12.2004 19:19
Probel   ты имеешь в виду, что можно запихнуть части grafi…   15.11.2005 23:36
Altair   мммм.. ну можно конечно... MeD что-то пробовал ..…   15.11.2005 23:41
Probel   мне б надо в TMT использовать все или почти все из…   15.11.2005 23:54
Altair   думаю поймешь что я имею ввиду.. library MyDLL; …   16.11.2005 0:02
Probel   спасибо а у нас тут где-нить на форуме про это р…   16.11.2005 0:07
Altair   вот тебе из DRKB:   16.11.2005 0:25
Altair   RE: P-robots   16.11.2005 0:26
Altair   RE: P-robots   16.11.2005 0:26
Probel   Altair, спасибки! :)   16.11.2005 1:29
Altair   Пожалуйста! Скачай DRKB не пожалеешь! :go…   16.11.2005 1:41
Probel   да, действительно классная вещь, спасибки за это …   16.11.2005 1:57
GoodWind   хм... портировать grafix по TMT что-ль.... а то из…   16.11.2005 12:28
Probel   GoodWind, давай, портируй, я рад буду :)   16.11.2005 20:57
volvo   Угу... Ты его лучше под FPC 2.0.0 сначала спортир…   16.11.2005 21:36
Altair   ставлю кефир что у него ничего не выйдет... уже п…   17.11.2005 0:23
arhimag   Люди а выставьте пожалуйста исходник первой версии…   17.11.2005 1:55
Altair   первой версии чего ??? Графикса ? на сайте ищи и …   17.11.2005 2:00
arhimag   Нет, п роботс!!   17.11.2005 2:02
Altair   http://pascal.sources.ru/gamestxt/probots4.htm   17.11.2005 2:28
Probel   а под TMT то можно пробовал кто-нить?   17.11.2005 2:37
Altair   сомневаюсь... если не получилось под тот же компи…   17.11.2005 2:51
Probel   эхх, мне б хотя бы чтоб jpeg загружать в tmt... м…   20.11.2005 22:37
GoodWind   FFC не пользую =)) портировать не буду... закончу …   21.11.2005 10:48
GoodWind   :lol: :lol: :lol: :lol: дату последнего поста …   23.12.2005 3:51
Gothic_Snake   :lol: :lol: :lol: :lol: дату последнего поста…   23.12.2005 22:00
virt   Ты ссылку дай куда выкладываете наработки.   24.12.2005 22:14
Gothic_Snake   Ты ссылку дай куда выкладываете наработки. В ско…   25.12.2005 17:56
arhimag   Я бы 3 или 4 рад быбыл поучаствовать :)))   24.12.2005 22:38
Gothic_Snake   Кстати, почему у меня не запускается проботс???   25.12.2005 18:30


 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 4.06.2024 2:41
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name