Классы в Delphi
От: star0ff  
Дата: 05.03.03 13:38
Оценка:
Здравствуйте,

Возникло желание выгрузить из основной программы мои классы и засунуть их в какую-то библиотеку (DLL)
Подскажите возможные пути решения.

Благодарю.
... << Megaherz — Wer Bist Du >>
Re: Классы в Delphi
От: star0ff  
Дата: 05.03.03 13:46
Оценка:
Здравствуйте, star0ff, Вы писали:

S>Здравствуйте,


S>Возникло желание выгрузить из основной программы мои классы и засунуть их в какую-то библиотеку (DLL)

S>Подскажите возможные пути решения.

S>Благодарю.


В смысле кроме COM Marshalling
... << Sister Machine Gun — Everything >>
Re[2]: Классы в Delphi
От: Slicer [Wirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 05.03.03 14:45
Оценка: 9 (1)
Приветствую.

Например, можно создать Run-time BPL (Borland Package Library).
По большому счету, это та же DLL, и она эскпортирует в т.ч. и члены классов.
(Можно запустить DUMPBIN или TDUMP и проверить. Причем TDUMP еще и имена расшифрует )
Так что можно ее через раннее или позднее связывание грузануть и работать.
Но сам я, если честно, не пробовал.
Одно знаю: если в Delphi объявить класс, то вместо его реализации можно написать
(правда, уже не помню- то ли в определение метода внутри определения класса, то ли после определения класса)
... MyMethod(<paramlist>); external 'MyCoolLibrary.dll';
и оно успешно компилится.

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[3]: Классы в Delphi
От: star0ff  
Дата: 05.03.03 15:17
Оценка:
Здравствуйте, Slicer [Wirkwood], Вы писали:

S[>Приветствую.

S[>Например, можно создать Run-time BPL (Borland Package Library).
S[>По большому счету, это та же DLL, и она эскпортирует в т.ч. и члены классов.
S[>(Можно запустить DUMPBIN или TDUMP и проверить. Причем TDUMP еще и имена расшифрует )
S[>Так что можно ее через раннее или позднее связывание грузануть и работать.
S[>Но сам я, если честно, не пробовал.
S[>Одно знаю: если в Delphi объявить класс, то вместо его реализации можно написать
S[>(правда, уже не помню- то ли в определение метода внутри определения класса, то ли после определения класса)
S[>... MyMethod(<paramlist>); external 'MyCoolLibrary.dll';
S[>и оно успешно компилится.

S[>Slicer

Не хотелось бы пользоваться BPL, по одной простой причине, возможно это мой грех, но хотелось бы пользоваться DLL, имхо солидней.
Второй вариант интереснее. Постараюсь про него найти инфу.

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

У меня есть набор каких-то классов. Как мне теперь перевести в DLL, интерфейсы с трудом понимаю

Идеально было бы написать что-то вроде:
...
var
  SomeObject:TSomeClass external 'SomeLib.dll';


Выглядит глупо, но думаю теперь смысл сразу понятен.

Возможно со временем система усложнится, сажем будет еще одна ChildClass.DLL в которой будут сидеть потомки ParentClass.Dll

А пока поломаю голову о книгу Стив Тейксейра, Ксавье Пачеко. Borland Delphi 5 Руководство разработчика, где вроде все это описывается.

Надеюсь Вы мне поможете (кое на что глаза мне уже открыли и на это огромное спасибо) разобраться в этом нелегком, ИМХО, вопросе.
... << MDFMK — Now >>
Re[2]: Классы в Delphi
От: Sinclair Россия https://github.com/evilguest/
Дата: 05.03.03 15:25
Оценка: 54 (5) -1
Здравствуйте, star0ff, Вы писали:
Как тут уже сказали, достаточно создать рантайм пакет (.bpl). Если проект скомпилирован с ключом Use Runitme Packages, то он весь код, который можно, выкинет наружу. Иначе он заимпортирует все dcu внутрь екзешника.
Никаких усилий по переделке классов производить не надо.
Мифы про использование ключевого слова external для импорта методов, а не процедур из DLL считаю байками.

В принципе, возможно также динамическое связывание с классами, вынесенными в DLL (а не BPL), но я бы очень не рекомендовал. Это много геморроя и неожиданных эффектов.

Краткая инструкция по вынесению функциональности в BPL:
1. Выполняем create new / Package
2. Добавляем в свежесозданный пакет интересующие нас юниты (сорц-файлы, ессно
3. Убираем эти юниты из проекта екзешника.
4. Включаем в опциях проекта галку "Use Runtime Packages" и убеждаемся, что наш пакет есть в списке рядом с ней.
5. Компиляем оба проекта.
6. Работаем и радуемся.
7. Если хотим отлаживать bpl, то помимо обычных приседаний (типа включения дебаг инфо), нужно в опциях исполнения пакета(в его проекте!) указать в качестве хоста главный проект и убедиться, что при запуске екзешника грузится именно тот bpl, который указан в настройках аутпута проекта пакета (типичная ошибка — копировать результирующий bpl рядом к екзешнику, и удивляться, почему брекпоинты не работают). После этого можно ставить брекпоинты в коде юнитов, входящих в пакет.
8. Рекомендую создать проджект груп, в которую будет входить сам пакет и екзешник. При этом поставить компиляцию пакета раньше чем екзешника. Поможнет легко переключаться между активными проектами при отладке и не забыть перекомпилять все, что надо, при внесении одновременных изменений.
... << RSDN@Home 1.0 beta 6 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Классы в Delphi
От: star0ff  
Дата: 05.03.03 15:46
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Краткая инструкция по вынесению функциональности в BPL:...



Все разжевано по самое не могу.

Но это не повод дублировать инструкцию целиком! ДХ
... << Korn — Twist-Chi (Live) >>
Re[3]: Классы в Delphi
От: Slicer [Wirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 05.03.03 16:41
Оценка: 76 (5)
Здравствуйте, Sinclair, Вы писали:

S>Мифы про использование ключевого слова external для импорта методов, а не процедур из DLL считаю байками.


Все согласны, что BPL=DLL?
Тогда смотрите:

Package1.dpk Uses Unit1
В unit1:

//interface
Type
  MyClass=class
    procedure Message;
    constructor Create;
  end;
//implementation
constructor MyClass.Create;
begin
  messagebox(0,'Text','Caption',mb_ok);
  inherited;
end;

procedure MyClass.Message;
begin
  messagebox(0,'Text','Caption',mb_ok);
end;


Project1.dpr Uses PUnit1
В PUnit1:


//interface
  TMyClass=class
    constructor Create;
    procedure Message;
  end;
//implementation
procedure TMyClass.Message;external 'package1.bpl' name '@Unit1@MyClass@Message$qqrv';
constructor TMyClass.Create;external 'package1.bpl' name '@Unit1@MyClass@$bctr$qqrv';

procedure TForm1.Button1Click(Sender: TObject);
var Obj:TMyClass;
begin
  Obj:=TMyClass.Create;
end;


Понимаю, это не очень практично.
Но похоже ли на миф?

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[4]: Классы в Delphi
От: Sinclair Россия https://github.com/evilguest/
Дата: 05.03.03 17:00
Оценка:
Здравствуйте, Slicer [Wirkwood], Вы писали:
1. Bpl != dll. Есть некторые нюансы.

SW>Понимаю, это не очень практично.

SW>Но похоже ли на миф?
Фантастика! Мой D5 это съел!
Я худею без баяна. Спасибо, коллега, век живи — век учись!
Если не секрет, откуда догадка? В доке явно не отрицается такая возможность, но и не упоминается...
... << RSDN@Home 1.0 beta 6 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Классы в Delphi
От: Slicer [Wirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 05.03.03 17:32
Оценка:
S>Если не секрет, откуда догадка? В доке явно не отрицается такая возможность, но и не упоминается...
Sinclair, честно, я уже и не помню. Я даже не использовал это никогда, просто зачем-то написал — и
удивился, что скомпилилось Верную фразу Whisperer (если не ошибаюсь) ввернул насчет того, что в
программировании интуиция иногда важнее всего оказывается

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[3]: Классы в Delphi
От: Bulfy Украина  
Дата: 07.03.03 01:31
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Краткая инструкция по вынесению функциональности в BPL:

...
S>7. Если хотим отлаживать bpl, то помимо обычных приседаний (типа включения дебаг инфо), нужно в опциях исполнения пакета(в его проекте!) указать в качестве хоста главный проект и убедиться, что при запуске екзешника грузится именно тот bpl, который указан в настройках аутпута проекта пакета (типичная ошибка — копировать результирующий bpl рядом к екзешнику, и удивляться, почему брекпоинты не работают). После этого можно ставить брекпоинты в коде юнитов, входящих в пакет.

Пишу прогу с использованием пакетов. Однако отладка указанным способом не включается, все брекпойнты зелёные
Танцы с бубном ситуацию не изменили. Пришлось писать проект без дебаггера (!) на данный момент это 80 тысяч строк, а я всё так же мучаюсь

Причём был светлый момент, когда после лазанья по настройкам дебаг вдруг включился. Поработал несколько дней, и как-то сам собой отключился. Понимаю, что звучит глупо, но никаких закономерностей в настройках компилятора и вкл/выкл дебага я не обнаружил. Все условия, приведённые в пред. письме соблюдены...
Игорь Бигдан.
Re[4]: Классы в Delphi
От: Sinclair Россия https://github.com/evilguest/
Дата: 08.03.03 02:20
Оценка:
Здравствуйте, Bulfy, Вы писали:

B>Причём был светлый момент, когда после лазанья по настройкам дебаг вдруг включился. Поработал несколько дней, и как-то сам собой отключился. Понимаю, что звучит глупо, но никаких закономерностей в настройках компилятора и вкл/выкл дебага я не обнаружил. Все условия, приведённые в пред. письме соблюдены...

Могу только посочувствовать. Увы, у Борланд очень странный подход к этому делу: столько неочевидных особенностей, что у людей возникает иллюзия недетерминированного поведения.
Уверяю вас, что на самом деле закономерности есть. Надо просто делать все очень аккуратно. Силишком много есть способов сбить эту тупую оболочку с толку, и она никогда не скажет, в чем же было дело...
... << RSDN@Home 1.0 beta 6 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Классы в Delphi
От: Slicer [Wirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 08.03.03 07:35
Оценка: 15 (3)
А вообще-то, мне больше нравится использовать интерфейсы.
Благо в Delphi это делается проще некуда:

library DllInt;

uses
  SysUtils,
  Classes,
  Windows;

Type IMyInt=interface
       ['{B90E3C5A-50EB-4F9B-BF3D-34A65E6E5B15}'] //Любой новый GUID
       procedure MyFunc;
     end;

     TMyClass=class(TInterfacedObject,IMyInt)
       procedure MyFunc;
     end;

{$R *.res}

{ TMyClass }

procedure TMyClass.MyFunc;
begin
  messagebox(0,'text','caption',MB_OK);
end;

function ReturnInt:IMyInt;
var T:TMyClass;
begin
  T:=TMyClass.Create;
  T.QueryInterface(IMyInt,result);
end;

exports ReturnInt;

begin
end.


А потом юзаем ее так:

//Unit1.pas:
Type IMyInt=interface
  //Копируем определение из исходника DLL (можно, конечно, инклуд или интерфейсный модуль сделать
  // с этим определением внутри (чтобы с Dll поставлять)
       ['{B90E3C5A-50EB-4F9B-BF3D-34A65E6E5B15}']
       procedure MyFunc;
     end;

function ReturnInt:IMyInt; external 'DllInt.dll';

procedure TForm1.Button1Click(Sender: TObject);
var I:IMyInt;
begin
  I:=ReturnInt;
  I.MyFunc;
  I:=nil;
end;


Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[2]: Классы в Delphi
От: star0ff  
Дата: 08.03.03 12:54
Оценка:
Здравствуйте, Slicer [Wirkwood], Вы писали:

Спасибо за примеры, без них ничего не получалось, теперь думается мне разберусь.
... << Adema — Everyone >>
Re[3]: Классы в Delphi
От: s.ts  
Дата: 20.10.03 16:08
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Мифы про использование ключевого слова external для импорта методов, а не процедур из DLL считаю байками.


Эта байка — не миф. Не вводите народ в заблуждение — ведь поверят же, особенно в обрамлении совершенно правильных фактов.

ИМХО можно так:


type
  TMy = class
    constructor Create;
  end;
<...>

constructor TMy.Create;external '...';//<- тут имя dll


Но все же настоятельно рекомендую воздержаться. Проще импортировать класс целиком. А еще проще использовать bpl.
Для солидности же все-таки рекомендую COM и ActiveX.

S>В принципе, возможно также динамическое связывание с классами, вынесенными в DLL (а не BPL), но я бы очень не рекомендовал. Это много геморроя и неожиданных эффектов.


Хочу добавить, что переносимости это тоже не добавит, т.е. как нельзя эти классы использовать в VB, так и останется.
Re[4]: Классы в Delphi
От: s.ts  
Дата: 20.10.03 16:13
Оценка:
блин. на даты не посмотрел... и кто этот топик наверх вытащил ??
Re[4]: Классы в Delphi
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 20.10.03 16:26
Оценка:
ST>Хочу добавить, что переносимости это тоже не добавит, т.е. как нельзя эти классы использовать в VB, так и останется.

А так ли это? Self — это просто еще один параметр. Блин, склероз — он до адреса возврата кладется или после, перед всеми параметрами? Если после, что мешает передавать его вручную куда надо?
Правда, это уже не класс будет для VB...

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[2]: Классы в Delphi
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 20.10.03 17:42
Оценка:
Здравствуйте, Slicer [Wirkwood], Вы писали:

SW>Благо в Delphi это делается проще некуда:


SW>
SW>library DllInt;

SW>uses
SW>  SysUtils,
SW>  Classes,
SW>  Windows;

.....................

SW>


А uses ShareMem? Иначе это сродни самоубийству... И вообще, это куча проблем, типа "Can't assign TFont to TFont"... Значит с раздельными пакетами компилить и эти пакеты с собой таскать... Надеяться что срастеться...

А вообще, зачем искать себе приключения, когда есть пакеты? Хоть интерфейсы, хоть классы...
Re[5]: Классы в Delphi
От: s.ts  
Дата: 21.10.03 06:44
Оценка:
Здравствуйте, Slicer [Mirkwood], Вы писали:


ST>>Хочу добавить, что переносимости это тоже не добавит, т.е. как нельзя эти классы использовать в VB, так и останется.


SM>А так ли это? Self — это просто еще один параметр. Блин, склероз — он до адреса возврата кладется или после, перед всеми параметрами? Если после, что мешает передавать его вручную куда надо?


Всегда сначала в стек запихиваются парметры, а потом адрес возврата. Очищается стек в зависимости от соглашений о вызове. Если сишное — стек чистит вызывающий (что-то типа add sp, ParamsSize ). Если паскалевское, то стек чистит тот, кого вызвали( что-то типа ret ParamSize );
Соответственно, никто не мешает передавать все вручную. Только замороки будут с виртуальными и динамическими методами — там нужно собственно адрес для вызова в VMT искать, формат которого [теоретически] известен только компилятору дельфи. Так или иначе для вызова виртуальных методов из VB без ассемблерных вставок не обойтись
Но это уже писание на ассемблере — там все можно, но не сразу, а немного помучавшись.
ИМХО не стоит овчинка выделки.
Re[5]: Классы в Delphi
От: Front Россия  
Дата: 21.10.03 06:52
Оценка:
Здравствуйте, s.ts, Вы писали:

ST>блин. на даты не посмотрел... и кто этот топик наверх вытащил ??

Я вытащил — появилась новая тема для обсуждения:
http://www.rsdn.ru/Forum/Message.aspx?mid=416319&amp;only=1
Front
Re: Классы в Delphi
От: Hacker_Delphi Россия  
Дата: 21.10.03 07:12
Оценка:
Здравствуйте, star0ff, Вы писали:

S>Возникло желание выгрузить из основной программы мои классы и засунуть их в какую-то библиотеку (DLL)

S>Подскажите возможные пути решения.
Единственный правильный путь — использовать пакаджи (кстати, изначально они именно для этого и предназначены)... благо для этого и делать особо ничего не надо — просто галку "Use Runtime Packages" включить... причем, если убрать оттуда стандартные — то они тебе прилинкуются, но лучше так не шутить....
... << RSDN@Home 1.1 beta 2 >>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.