![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Экспорт / импорт (dll) функций из класса [D7]
parovoZZ © (2006-06-27 05:35:00)
Страницы: < 1 2 3 4 5 6 7 8 9 10 >
К примеру, запись
exports
TMyClass.myFunc name 'MyFunc';
ошибочна. А как быть?
Пусик (2006-06-29 21:24:00) [21]DLL1:
library FType1;
uses
windows,
SysUtils,
Classes,
uParentClass in '..\uParentClass.pas';
type
TMainDLLClassType1=class(TMainDLLClass)
public
constructor Create(const FilePath: String);
function ProcessFile: Boolean; override;
end;
{ TMainDLLClassType1 }
constructor TMainDLLClassType1.Create(const FilePath: String);
begin
inherited Create(FilePath);
end;
function TMainDLLClassType1.ProcessFile: Boolean;
begin
inherited ProcessFile;
Result := True;
//Здесь обработка файла нужного типа.
end;
function Process(FilePath: DWORD): BOOL; stdcall;
var
Obj: TMainDLLClassType1;
begin
Result := False;
try
Obj := TMainDLLClassType1.Create(PChar(FilePath));
try
Result := Obj.ProcessFile;
finally
Obj.Free;
end;
except
end;
end;
exports
Process;
end.
Пусик (2006-06-29 21:23:00) [22]Реализация родительского класса:
unit uParentCLass;
interface
uses
classes;
type
TMainDLLClass=class
public
FFIlePath: String;
FL: TStringList;
constructor Create(const FilePath: String);
destructor Destroy; override;
function ProcessFile: Boolean; virtual;
end;
implementation
{ TMainDLLClass }
constructor TMainDLLClass.Create(const FilePath: String);
begin
FFIlePath := FilePath;
FL := TStringList.Create;
end;
destructor TMainDLLClass.Destroy;
begin
FL.Free;
inherited;
end;
function TMainDLLClass.ProcessFile: Boolean;
var
i: Integer;
begin
Result := False;
try
FL.LoadFromFile(FFIlePath);
for i := FL.Count - 1 downto 0 do
begin
if FL[i]='' then FL.Delete(i);
end;
FL.SaveToFile(FFIlePath);
Result := True;
except
end;
end;
end.
Пусик (2006-06-29 21:22:00) [23]Ну что же.
Пример я таки сделала.
Весьма схематично, но код рабочий.
Основной модуль:
unit ufMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm4 = class(TForm)
Button1: TButton;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
end;
TProcessFile=function(FilePath: DWORD): BOOL; stdcall;
var
Form4: TForm4;
HandleArray: array of THandle;
ProcArray: array of TProcessFile;
implementation
{$R *.dfm}
procedure GetFiles(const aPath: String;var aListFile: TStringList);
var
SR: TSearchRec;
tPath: String;
begin
{$WARN SYMBOL_PLATFORM OFF}
tPath := IncludeTrailingBackSlash(aPath);
if FindFirst(tPath+'\*.*',faAnyFile,SR)=0 then
begin
try
repeat
if (SR.Name='.') or (SR.Name='..') then Continue;
if (SR.Attr and faDirectory)<>0
then Continue
else aListFile.Add(tPath+SR.Name);
until FindNext(SR)<>0;
finally
Sysutils.FindClose(SR);
end;
end;
{$WARN SYMBOL_PLATFORM ON}
end;
procedure TForm4.Button1Click(Sender: TObject);
var
L: TStringList;
Ext: String;
i: Integer;
begin
L := TStringList.Create;
try
GetFiles('c:\temp',L);
for i := 0 to L.Count - 1 do
begin
Ext := AnsiUpperCase(ExtractFileExt(L[i]));
if Ext='.TXT' then ProcArray[0](DWORD(PChar(L[i])));
if Ext='.DBF' then ProcArray[1](DWORD(PChar(L[i])));
end;
finally
L.Free;
end;
end;
procedure TForm4.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FreeLibrary(HandleArray[0]);
FreeLibrary(HandleArray[1]);
end;
procedure TForm4.FormCreate(Sender: TObject);
var
H: THandle;
Proc: TProcessFile;
begin
SetLength(HandleArray,2);
SetLength(ProcArray,2);
H := LoadLibrary('Dll1\FType1.dll');
HandleArray[0] := H;
@Proc := GetProcAddress(H,'Process');
ProcArray[0] := @Proc;
H := LoadLibrary('Dll2\FType2.dll');
HandleArray[1] := H;
@Proc := GetProcAddress(H,'Process');
ProcArray[1] := @Proc;
end;
end.
Almaz (2006-06-29 21:05:00) [24]
> Конечно, не дураки, но всего лишь люди.
> Из той же BDE (царствие ей небесное)
> уж никак не получилась классическая dll.
Аминь ;))
> И иной раз приходилось таки перегружаться,
> из-за некорректной ее финализации.
Там проблем хватало и без финализации ;)
Leonid Troyanovsky (2006-06-29 20:57:00) [25]
> Almaz © (29.06.06 20:39) [161]
> Borland'a такими уж дураками, не знающими , что "исполнение
> кода при этом самом detach отягощена некоторыми особенностями"
> ;)))
Конечно, не дураки, но всего лишь люди.
Из той же BDE (царствие ей небесное)
уж никак не получилась классическая dll.
И иной раз приходилось таки перегружаться,
из-за некорректной ее финализации.
--
Regards, LVT.
Almaz (2006-06-29 20:39:00) [26]Господа, позвольте уж и мне вставить реплику в Вашу милую беседу...
Оставив вопрос об экспорте/импорте объектов и классов из DLL, как уже решенный в этой теме, выскажусь по поводу использования классов внутриреализации функций DLL.
Во-первых, ИМХО, спорящие забыли упомянуть исключениях, представленных в Дельфи классомException. Даже при процедурном программировании их применение часто позволяет сильно упростить код, избавив его, например, от множества ветвлений при последовательности сложных проверок и т.п.
Во-вторых, позволю напомнить о такой "разновидности" DLL, как CPL. Дельфи предлагает реализовывать эти DLL на основе класса TAppletModule и, собственно, VCL. Вы предпочитаете писать CPL на WinAPI ? Я нет - мне дороже мое время.
В-третьих вся реализация COM-серверов в DLL в Delphi от начала и до конца строится на ООП. (хотя про СОМ разговор особый - это конечно же не классические DLL)
Теперь немного о приведенных выше аргументах против:
> Допустим даже, что у нас есть доводы за dll.
> Как, собс-но, мы должны применить ООП?
> Видимо:
> 1. Создать объект
> 2. Заполнить его поля некоторыми простых типами,
> переданными из хоста.
> 3. Сделать некоторые пассы.
> 4. Вернуть хосту нужные простые типы из полей.
> 5. Разрушить объект.
>
> Налицо некоторые overheads. Т.е., все это совершенно спокойно
> можно свести к неким преобразованиям простых типов,
Пока речь идет о классе типа TList - это да, это аргумент. Но вот есть у меня класс, ответственный за распознавание текста - его реализация занимает огромное число строчек кода и буде он мне понадобится в DLL мне и в голову не придет потратить несколько дней на выколупование отдельных процедур из этого класса - все равно, время, потраченное программой на создание/удаление экземпляра этого класса ничтожно по сравнением с исполнением задачи процедурой. Оптимизация должна быть разумной - разве я неправ ?
> без мучительных раздумий, как уследить за распределенной
> в длл памяти,
Разве в промежутке от 1 до 6 исполнение может быть прервано извне без завершения вызвавшего функцию потока ? А раз нет, то и никаких раздумий у нормального программиста не должно возникать.
> что будет, если будет повторный вызов в промежутке
> между 1 - 6 и т.д."
Собственно, ничего не будет, если поток создается и разрушается при каждом вызове.
Позволю себе немного обобщить - использование ООП внутри DLL, ИМХО, не привнесет никакого криминала, кроме некоторых накладных расходов связанных с соданием и разрушением объектов, которые имеет смысл учитывать лишь тогда, когда они соизмеримы со временем выполнения процедуры.
p.s. При создании DLL в Delphi через пункт New.., Delphi включает в нее модули SysUtils и Classes тем самым обуславливая создание как минимум 8 объектов ;)) Не будем считать программистов Borland'a такими уж дураками, не знающими , что "исполнение кода при этом самом detach отягощена некоторыми особенностями" ;)))
Leonid Troyanovsky (2006-06-29 20:37:00) [27]
> Fay © (29.06.06 19:50) [159]
> Понимаю, у Вас найдутся дела и поинтереснее, но пока все
> стороны воздерживаются от примеров (которые можно "потрогать"),
> приходится верить (или нет) на слово.
Вот, когда я был маленький, я тоже каждый год ездил ..
пардон, мечтал о разных скинах-плагинах, динамически
подключаемых формах и пр.
И был очень рад, открыв для себя такую во всем замечательную
вещь как dll (уж про, например, dll hell, я тогда и понятия не имел).
Долго искал, мучился, эксперементировал с переменным успехом,
пока старшие товарищи не научили смотреть на вещи без розовых очков.
Эти принципы я усвоил, позволю их повторить:
1. использовать dll только тогда, когда без оной обойтись нельзя.
2. не использовать объекты в in, out & inside dll.
После & - это уже мои собс-ные выводы на базе определенного
эмпирического опыта воспроизведения трудноуловимых глюков.
Правда, примеры я не коллекционировал, бо, видимо, не
задумывался о их полезности в нынешней дискуссии.
Однако, неприятные ощущения от того опыта остались.
Они легко воспроизводятся при словах dll+OOP.
Кстати, я еще давно заметил, что сторонники dll+OOP обычно
напористы и агрессивны (маньякально-депрессивны -шут.)
Видимо, каждый из них проходит через "озарение" (И был очень рад..),
и искренне полагает, что все дельфийское сообщество прошло стороной.
Ну, а ларчик открывается просто.
MS не было нужды (= не было возможности) делать dll
объектно ориентированной.
Когда оные нужды созрели - появился и COM и .NET.
Какие уж тут, dll. Пора, IMHO, оставить старушку в покое :)
Извини, брат, за отсутствие кода,
театр закрывается, нас всех тошнит (с) Хармс.
--
Regards, LVT.
Fay (2006-06-29 19:50:00) [28]2 Leonid Troyanovsky © (29.06.06 19:35) [158]
Думаю, многие уже готовы посмотреть на иллюстрацию к сказанному в [158] о возможных проблемах.
Понимаю, у Вас найдутся дела и поинтереснее, но пока все стороны воздерживаются от примеров (которые можно "потрогать"), приходится верить (или нет) на слово.
У меня, к примеру, с момента [80] так и не появилось никакого мнения ни о сабже, ни об остальном в этой ветке.
Мне пока совершенно не очевидно изящество решения Пусика [150] (жду с нетерпением уточнений по экп-м ф-ям), как и реальность проблем из [158].
Leonid Troyanovsky (2006-06-29 19:35:00) [29]
> Fay © (29.06.06 15:31) [127]
> > говорит это в контексте сабжа, в контексте импорта/экспорта
> Не поверю в это, пока он сам этого не скажет.
Правильно, не верь :)
Что есть dll? PE, который вписывается в запущенный процесс.
Его назначение - загружаться и выгружаться динамически.
в некоторые, определенные кодом экзешника процесса моменты.
Заметим, что моменты этих вызовов могут определяться
неким хостом, которому глубоко безразлична дельфийская
объектная модель. Т.е., ему фиолетова правильная инициализация,
правильное использование и разрушение неких объектов и
их последовательность.
Да и как он может знать о правильности, если оная модель
ему недоступна? Значит, весь труд по правильному применению
нутренных объектов лежит на совести разработчика.
Предположим, что все 6 шагов уложились в один внешний вызов.
В этом случае, как уже отмечалось, достаточно скопировать
(с некотрыми преобразованиями) код вызываемых методов в
обычные процедуры (и чего там такого сверхестественного
могут делать эти методы).
Т.е., в данном случае достаточно убрать накладные
расходы, связанные с самими объектами.
Вполне посильная задача с вполне приемлемым результатом.
Кстати, и бонус возможен - т.е., за счет использования только
простых типов область применения может стать даже шире,
чем у исходного объекта.
Случай второй: для экономии мы создадими объект
один раз, а уж пользовать будем его во все дыры.
Т.е., между 1 и 6 возможен зазор.
Ну, а тогда у нас новые проблемы, нужна (необъектная)
ссылка на объект, определяемая при его создании,
хранящеся не только у хоста, но и в некотором
внутреннем списке, с помощью которого мы
будем рассчитывать корректно оные объекты
освободить, если вдруг DLL_PROCESS_DETACH.
Но, маленькая загвоздка -исполнение кода при
этом самом detach отягощена некоторыми особенностями.
(Кстати, они могут быть не только внутри windows, но
и внутри дельфийского rtl). Так как оным завершателям
наши заботы ульрафиолетовы, а управлять оным
процессом, видимо, невозможно, нам остается лишь
время от времени лечиться у доктора Ватсона.
Ну, и , наконец, представим, что нашу библиотеку
решили (скажем, в угоду прогрессу) отдать сразу
нескольким потокам (да на нескольких процессорах).
А чего - вполне реально ;)
Делать выводы каждый сам.
Свое мнение я уже говорил.
Богу- богово, кесарю - кесарево.
-
Regards, LVT.
Fay (2006-06-29 19:03:00) [30]2 Пусик © (29.06.06 18:56) [154]
> Ну замени слово "протокол" на "тип файла"?
Заменил. Те же яйца.
Правда, я не имею ни малейшего представления об экспортируемых функциях.
А ваще, мне пофиг.
Пусик (2006-06-29 18:59:00) [31]
> Leonid Troyanovsky © (29.06.06 18:53) [153]
И не надо недержания.
Пусик (2006-06-29 18:58:00) [32]
> Leonid Troyanovsky © (29.06.06 18:53) [153]
> Ну, и хватит брызгать слюной, здесь
> собираютсявполне, IMHO, серьезные люди.
Не похоже.
Пусик (2006-06-29 18:56:00) [33]
> Romkin © (29.06.06 18:30) [151]
> То есть, одна dll - один класс? Я спрашивал именно о способе
> общения с классом в библиотеке. Как он происходит в данном
> случае? По второму способу? Или классы передаются за пределы
> dll?
Способ общения:
- Модуль с родительским классом используется в каждой из DLL.
- В каждой DLL, кроме родительского класса, используется один наследник с нужным функционалом.
- Основное приложение получает(откуда-то) нотификацию о поступлении информации, определяет необходимую для обработки DLL и вызывает функцию из нужной DLL(Не метод!), передавай(неважно, каким образом) необходимую информацию в DLL.
- Далее в DLL уже обрабатывается эта информация.
Методы линковки - неважные частности в данном случае.
> Fay © (29.06.06 18:37) [152]
> Мне кажется (м.б. только мне), в [150] приведён очень неудачный
> (на редкость) пример. Ну зачем делать протокол классом?
Ну замени слово "протокол" на "тип файла"?
Leonid Troyanovsky (2006-06-29 18:53:00) [34]
> Пусик © (29.06.06 18:23) [150]
> Т.е., как я поняла, позиция уже немного поменялась? Если
> раньше говорилось о том, что надо всячески избегать использования
> ООП, так как это множит сущности, то теперь оврится лишь
> об исключительных случаях, когда применение ООП не рекомендуется?
Дык, конечно, речь об этих (исключительных) случаях -
об использовании ООП в dll.
Хочется дельфийского ООП - пиши все в экзешник.
Хочется dll - извольте-с опуститься к простым типам-с.
Хочется чего-то еще - юзайте COM.
Ну, и хватит брызгать слюной, здесь собираются
вполне, IMHO, серьезные люди.
--
Regards, LVT.
Fay (2006-06-29 18:37:00) [35]Мне кажется (м.б. только мне), в [150] приведён очень неудачный (на редкость) пример. Ну зачем делать протокол классом?
Romkin (2006-06-29 18:30:00) [36]То есть, одна dll - один класс? Я спрашивал именно о способе общения с классом в библиотеке. Как он происходит в данном случае? По второму способу? Или классы передаются за пределы dll?
Пусик (2006-06-29 18:23:00) [37]
> Игорь Шевченко © (29.06.06 17:30) [148]
> Пусик © (29.06.06 17:12) [147] > Следуя логике Игоря Шевченко,
> можно подумать, что следует > вообще отказаться от использования
> ООП, так как это увеличивает > количество сущностей.[140]
> до полного и окончательного просветления
Ешьте сами с волосами. И просветляйтесь.
> В случае единого приложения или в случае, если разбиение
> приложения не влечет за собой дополнительной работы, головная
> боль отсутствует и сущности, как ни странно, не умножаются.
Поясни, что такое "Единое приложение". Термина не поняла.
> Впрочем, есть примеры, когда ООП не приносит никакого выигрыша.
>
Вот именно. Существует не очень большой круг задач, где ООП не приносит выигрыша. Но в подавляющем большинстве случаев (мы же не говорим о программе "Здравствуй, Мир!") ООП является большим подспорьем программисту.
------
Т.е., как я поняла, позиция уже немного поменялась? Если раньше говорилось о том, что надо всячески избегать использования ООП, так как это множит сущности, то теперь оврится лишь об исключительных случаях, когда применение ООП не рекомендуется?
> " - Мудро. Руководствуйтесь этим принципом и впредь.
Очень любезно с твоей стороны понять и принять эту точку зрения.
> Romkin © (29.06.06 17:30) [149]
> Пусик © (29.06.06 17:12) [147] [129] и [136] Мне казалось,
> что вопрос исчерпан, а тут опять.> совершенно неопрадан
> отказ от ООП, как средства быстрой разработки, масштабируемости
> приложений и удобства дальнейшего сопровожденияВ посте 129
> я описал способы организации объектов в dll. Какой способ
> ты предлагаешь?
Ты считаешь, что этими вариантами применение ООП исчерпывается?
Не согласна. Навскидку предложу еще один вариант(а лучше пример):
Задача - прием и обработка информации, приходящей по каналам связи.
Данные приходят в различных форматах, для передачи используются различные протоколы. После обработки данные помещаются в файлы на диск, в основное приложение передается только статистическая информация.
Обработка файлов должна проводиться в режиме 24/7.
Для реализации используется ООП.
<родительский класс-протокол>-MainDLL-->
<Дочерний класс-протокол1>-Prot1DLL
<Дочерний класс-протокол2>-Prot2DLL
...
<Дочерний класс-протоколN>-ProtNDLL
Периодически список обрабатываемых протоколов изменяется - одни устаревают и удаляются, новые появляются.
Весь функционал реализован в DLL.
Для обновления списка используемых протоколов в основной программе редактируется соответствующий список.
Небольшой нюанс: как в родительском, так и в дочерних классах реализован достаточно большой объем обработки.
-------------------
Вот такая простая задача.
Возможен такой вариант? Возможен.
Та же задача может быть реализована другими способами? Может.
А смысл использовать другой способ? Почему не этот? Из-за дурацкой мысли, что ООП в DLL - это плохо?
Romkin (2006-06-29 17:30:00) [38]Пусик © (29.06.06 17:12) [147]
[129] и [136] Мне казалось, что вопрос исчерпан, а тут опять.
> совершенно неопрадан отказ от ООП, как средства быстрой разработки, масштабируемости приложений и удобства дальнейшего сопровождения
В посте 129 я описал способы организации объектов в dll. Какой способ ты предлагаешь?
Игорь Шевченко (2006-06-29 17:30:00) [39]Пусик © (29.06.06 17:12) [147]
> Следуя логике Игоря Шевченко, можно подумать, что следует
> вообще отказаться от использования ООП, так как это увеличивает
> количество сущностей.
[140] до полного и окончательного просветления
> При решении любой заачи необходимо руководствоваться принципом
> целесообразности, а не личными тараканами в голове(что тоже
> неплохо иногда, но тараканы-то - личные, и не стоит их выносить
> в общество).
" - Мудро. Руководствуйтесь этим принципом и впредь. Благодарю вас за
внимание, Штирлиц." (с) Альтернатива
Пусик (2006-06-29 17:12:00) [40]
> Romkin © (29.06.06 16:56) [146]
> Многоуважаемые господа, позвольте мне, как скромному читателю
> Ваших реплик, нижайше поинтересоваться Вашими планами и
> замыслами дальнейшего развития сего, без сомнения будь сказано,
> наизамечательнейшего диалога?:-Р
Вот я и вернулась ;-)
Вообще, я планировала услышать не менее весомые(как в случае экспортирования классов) аргументы в пользу отказа от использования ООП в DLL.
Здесь много говорилось об сложностях с экспортом классов и их методов, дискуссия давно уже вышла из рамок топика.
Как уже выше писала, аргументов не видно.
Следуя логике Игоря Шевченко, можно подумать, что следует вообще отказаться от использования ООП, так как это увеличивает количество сущностей. Но ведь процесс программирования ценен не сам по себе, а лишь как средство для решения различных прикладных и системных задач.
С точки зрения системмных задач можно согласиться с нектороыми утверждениями и отказом от ООП во многих случаях. Но с точки зрения прикладного программирования совершенно неопрадан отказ от ООП, как средства быстрой разработки, масштабируемости приложений и удобства дальнейшего сопровождения.
При решении любой заачи необходимо руководствоваться принципом целесообразности, а не личными тараканами в голове(что тоже неплохо иногда, но тараканы-то - личные, и не стоит их выносить в общество).