![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как достать фрейм из bpl ? [D2, D3, D4, D5, D6, D7, Win95/98, WinME, NT4, Win2k, WinXP]
BFG9k © (2005-10-07 16:02:00)Создаю пакет, включаю в него unit с фреймом.
Помпилирую пакет ,получаю bpl.
В другом проекте загружаю bpl с помощью LoadPackage. Можно ли достать фрейм из bpl и кинуть на форму этого проекта ?
REA (2005-10-12 15:55:00) [1]Вариант 1:
Переменная M где-то портится.
Вариант 2:
Обработчики фрейма могут быть в BPL. При попытке вызова обработчика при выгруженной BPL - AV.
Вот это ничего не даст, т.к. во Free и так проверяется Assigned.
if Assigned(Frame1) then
Frame1.Free;
BFG9k (2005-10-12 14:56:00) [2]Но AV возникает как раз в том случае, если я НЕ убиваю фрейм в finalization (даже если я нигде его не убиваю). Вот я и думаю, к чему бы это.
REA (2005-10-12 10:57:00) [3]Owner у Frame форма, она его и убъет.
Frame1.Free уже может работать по невалидной ссылке.
BFG9k (2005-10-11 17:19:00) [4]Да, видимо у меня невалидная ссылка.
Делаю следующим образом:
procedure TForm1.FormCreate(Sender: TObject);
var Flags:integer;
begin
M:=LoadPackage('Packages\Package1.bpl');
@FrameConstructor:=GetProcAddress(M,'CreateFrame');
if Assigned(FrameConstructor) then
Frame1:=FrameConstructor(Self,Self);//Первое - Owner , второе - Parent
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Frame1.Free;//можно не освобождать - результат тот же
UnloadPackage(M);//возникает Access Violation
end;
Так вот, AV не возникает, если в пакете сделать следующее :
implementation
var Frame1:TFrame1;
{$R *.dfm}
function CreateFrame(AOwner:TComponent;AParent:TWinControl):TFrame;
begin
Frame1:=TFrame1.Create(AOwner);
Frame1.Parent:=AParent;
Result:=Frame1;
end;
exports
CreateFrame name 'CreateFrame';
initialization
Frame1:=nil;
finalization
if Assigned(Frame1) then
Frame1.Free; // в этом случае выгрузка происходит корректно
end.
Frame1 в пакете и программе - разные указатели, но на одну и ту же структуру (просто имена совпадают).
Reindeer Moss Eater (2005-10-11 16:09:00) [5]Если делать это в главной программе,
Нет никакой разницы где это делать.
Если у тебя AV, значит у тебя либо невалидная ссылка, либо ошибка в программе.
BFG9k (2005-10-11 15:04:00) [6]Если делать это в главной программе, то при вызове UnloadPackage имеем Access Violation. Ладно, сделаю индексацию динамическим массивом, это не долго.
Reindeer Moss Eater (2005-10-11 14:37:00) [7]Можно ли как-либо уничтожать экземпляр фрейма, имея только ссылку на него ?
<ссылка на него>.Free
BFG9k (2005-10-11 14:19:00) [8]Точно!
И последний вопрос: как лучше уничтожать созданные экземпляры фрейма ? При вызове Unload Package возникает Access Violation, если фрейм не уничтожить. Просто написать в основной программе Frame1.Free - не проходит. С одним экземпляром проблем нет - уничтожать его в DLL. Для нескольких экземпляров необходимо уже вести их индексацию в DLL. Можно ли как-либо уничтожать экземпляр фрейма, имея только ссылку на него ?
REA (2005-10-11 13:30:00) [9]Скомпилировать все с включенными run-time packages.
BFG9k (2005-10-11 13:28:00) [10]Спасибо. Никогда не подозревал, что раздел Exports может существовать прямо в модуле фрейма.
Однако не все так хорошо, как могло бы показаться. Попытался создать фрейм с одной кнопкой. Фрейм создался. В начале вылезла ошибка : Cannot assign TFont to TFont. При уничтожении фрейма - Access Violation.
Нашел статью о загрузке обьектов из DLL : http://www.delphimaster.ru/articles/book/Chap09.pdf
Смущает пункт 3 требований к DLL :
"Экспортируемый объект должен быть определен как в DLL , так и в вызывающем приложении с помощью методов, определенных в том же порядке."
2 раза определять объект?! Смысл применения DLL в таком случае пропадает.
Обнадеживает следующая фраза :
"Используемый подход применяется в весьма специфических ситуациях, и , как правило, такого же эффекта можно достичь путем применения пакетов и интерфейсов".
Применение энтерфейсов при взаимодействии Delphi с Delphi не обосновано. Я применяю пакеты, к сожалению в статье не сказано, как их применять :(
Reindeer Moss Eater (2005-10-10 17:05:00) [11]LoadPackage
EnumModules
Затем ищи с пом. GetProcAddress в модулях процедуру с предопределенным тобой именем: '@' + <Имя_Модуля> + '@' + <Имя_процедуры> + '$qqrv'
Она тебе и создаст нужный фрейм.
BFG9k (2005-10-10 16:40:00) [12]Нашел неплохую статью на эту тему : http://www.delphimaster.ru/articles/bdform/index.html
Правда все как-то через анус реализованно (хакерскими методами, я имею в виду).
BFG9k (2005-10-10 16:24:00) [13]Попробовал оба варианта.
1) Не нашел как экспортировать функцию из пакета. Можно ли вообще это сделать (в contains указываются только модули)? Попробовал сделать то же самое с DLL. Получилось вернуть Handle создаваемой формы, но не фрейма. Как только происходит обращение к Parent - исключение EInvalidOperation. При попытке вернуть экземпляр формы/фрейма - то же самое.
Привожу код DLL :
function CreateFrame(AParent:THandle):THandle;
begin
Form1:=TForm1.CreateParented(AParent);
Result:=Form1.Handle;
end;
procedure DestroyFrame;
begin
Form1.Free;
end;
Exports
CreateFrame name 'CreateFrame',
DestroyFrame name 'DestroyFrame',
begin
end.
С фреймом то же самое не проходит - вылетает на CreateParented. Подозреваю, что TForm/TFrame вернуть невозможно в принципе :(
2) Делаю RegisterClass в разделе initialization модуля с фреймом. Секция выполняется - проверял. Загружаю пакет - FindClass ничего не находит.
REA (2005-10-07 17:56:00) [14]Можно поступить следующими способами:
1) Экспортировать функцию - конструктор фрейма, возвращающую фрейм (базовый класс)
2) Зарегистрировать в bpl класс при помщи RegisterClass, найти его в программе и создать на основе метакласса объект.