Текущий архив: 2005.10.30;
Скачать: CL | DM;
ВнизНе закрывается приложение при работе с DLL Найти похожие ветки
← →
Norfolk © (2005-10-04 22:43) [0]Уважаемые Мастера.
Имеется приложение, которое вызывает форму из DLL. Всё работает как надо, форма из библиотеки вызывается, но когда форма заканчивает работать программа не закрывается, возникает ошибка, что-то вроде Приложение обратилось к памяти по адресу ...(адрес).... Память не может быть "Read". Нажмите ОК для завершения приложения. Такая ошибка возникает только если форма в библиотеке хоть немного сложная и насыщеная элементами. Если же форма в DLL пустая или на ней всего пару кнопок - то всё нормально, всё закрывается и работает.
← →
Германн © (2005-10-05 00:30) [1]А стоило ли пихать форму в DLL?
Столько уже истрачено черных пикселей на слова о "кривости" данного подхода.
← →
Delphi_is_cool © (2005-10-05 00:46) [2]Подключен ли модуль ShareMem ?
Если нет, то его нужно подключить в Dll"ке и в самом проекте(Project->View Source)
ps
Лчуше вместо модуля ShareMem использовать модуль FastShareMem(его можно найти в интернете).
← →
GanibalLector © (2005-10-05 02:38) [3]2 Norfolk © (04.10.05 22:43)
Тысяча элементов тебя устроит???
DLL :
library Project1;
uses
SysUtils,
Classes,
Unit1 in "Unit1.pas" {Form1};
Exports
ShowMyForm;
{$R *.RES}
begin
end.
\\\\\\\\\\\\\\\
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
private
public
procedure CClick(Sender: TObject);
end;
procedure ShowMyForm(Handle:HWND);stdcall;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure ShowMyForm(Handle:HWND);stdcall;
var Frm:TForm;
begin
Application.Handle:=Handle;
Frm:=TForm1.Create(Application);
try
Frm.ShowModal;
finally
Frm.Release;
Frm.Free;
end;
end;
procedure TForm1.CClick(Sender: TObject);
begin
ModalResult:=MrOk;
end;
procedure TForm1.FormCreate(Sender: TObject);
var i:Integer;
h:TButton;
begin
Randomize;
for i:=1 to 1000 do
begin
h:=TButton.Create(Self);
h.Parent:=Self;
h.Top:= Random(Self.Top);
h.Left:=Random(Self.Left);
h.Caption:="MyButton"+IntToStr(I);
h.OnClick:=CClick;
end;
end;
end.
Вызов библиотеки :
const DLLName="Project1.dll";
procedure TForm1.Button1Click(Sender: TObject);
var h:THandle;
ShowMyForm:procedure(Handle:HWND);stdcall;
begin
h:=LoadLibrary(DLLName);
if h>0 then
begin
ShowMyForm:=GetProcAddress(h,PChar("ShowMyForm"));
if Assigned(ShowMyForm) then
ShowMyForm(Application.Handle);
FreeLibrary(h);
end;
end;
← →
GanibalLector © (2005-10-05 02:40) [4]З.Ы. Писал ночью,так что не судите строго. Одно скажу, MemProf сказал что утечек НЕТ. :))
← →
GanibalLector © (2005-10-05 02:43) [5]2 Delphi_is_cool © (05.10.05 00:46) [2]
>Подключен ли модуль ShareMem ?
В комментарии указывается на необходимость вставить ссылку на модуль ShareMem, если библиотека экспортирует длинные строки в параметрах обращения к подпрограммам или как результат функций. При чем тут вызов форм???
← →
Babay © (2005-10-05 08:01) [6]Очень знакомо, я уже как-то об этом писал, правда сначала сам задавал подобный вопрос. Думаю у Вас тоже самое ;-)
А как Вы подключаете DLL? статически или динамически?
У меня была такая проблема когда используется XPManifest. Ошибку так и неудалось выловить больно глубоко закопана.
Лечится ДИНАМИЧЕСКИМ подключением библиотеки.
То GanibalLector
с тысячей кнопок такой ошибки нет, да и срядом других элементов тоже. Вы поробуйте например StringGrid на форму кинуть, и не забудьте про XPManifest в приложении. В случае статического подключения получите эту ошибку. Если убрать манифест ошибки нет.
← →
Norfolk © (2005-10-05 22:11) [7]
> Очень знакомо, я уже как-то об этом писал, правда сначала
> сам задавал подобный вопрос. Думаю у Вас тоже самое ;-)
>
> А как Вы подключаете DLL? статически или динамически?
> У меня была такая проблема когда используется XPManifest.
> Ошибку так и неудалось выловить больно глубоко закопана.
>
> Лечится ДИНАМИЧЕСКИМ подключением библиотеки.
>
> То GanibalLector
> с тысячей кнопок такой ошибки нет, да и срядом других элементов
> тоже. Вы поробуйте например StringGrid на форму кинуть,
> и не забудьте про XPManifest в приложении. В случае статического
> подключения получите эту ошибку. Если убрать манифест ошибки
> нет.
Библиотека подключается так:procedure RunEditorForm(AOwner: TComponent);
external "editor.dll";
...
procedure TSettingsDlg.RunEditTestBtnClick(Sender: TObject);
begin
RunEditorForm(Self);
end;
← →
Юрий Зотов © (2005-10-06 07:56) [8]> Norfolk © (05.10.05 22:11) [7]
Похоже, что дело в параметре AOwner (при завершении программы DLL пытается что-то сделать, используя полученную ссылку на этот компонент - а в этот момент он уже уничтожен в EXE).
← →
Babay © (2005-10-06 08:37) [9]То Юрий Зотов © вы совершенно правы. Ошибка происходит гдето в менеджере ХР стилей в VCL. Как я и говорил докопаться неудалось. Знаний не хватает.Я не большой спец :-), да это и не основная моя работа.
А вот если б Вы Юрий докопались было бы весьма интересно Ваше мнение.
То Norfolk © у Вас статическое подключение библиотеки, вам нужно сделать динамическое, то есть библиотека должна грузится не вместе с приложением, а когда она необходима. Мне это помогло. Инфы как это делается должно быть в инете много, если не получится пишите сделаю для Вас пример.
← →
evvcom © (2005-10-06 09:30) [10]
> А вот если б Вы Юрий докопались было бы весьма интересно
> Ваше мнение.
А чего тут копать? Кривой подход - кривой результат. Нельзя ссылаться на классы, реализованные в другом модуле, так как это "чужеродные" типы. Это если не используются run-time пакеты.
← →
Babay © (2005-10-06 09:57) [11]То evvcom ©
Поясняю (мож я неправильно выразился)
Итак создаем новую длл в которой есть одна только форма и StringGrid на ней.
в ней пишем функциюlibrary myDll;
uses
SysUtils,
Classes,
Udll in "Udll.pas" {Form1};
{$R *.res}
Procedure ShowForm;
Var F:TForm1;
Begin
f:=Tform1.Create(nil);
f.ShowModal;
f.Free;
end;
exports ShowForm index 1 name "ShowForm";
begin
end.
Созлаем приложение с одной кнопкой которая вызывает функцию из DLLprocedure ShowForm;external "myDll.dll";
........
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowForm;
end;
запускаем приложение, жмем кнопку, закрываем форму, выходим. Все Ок.
Добавляем в приложение XPManifest.
запускаем приложение, жмем кнопку, закрываем форму, выходим.
Access violation..... при выходе.
Покажите мне > "чужеродные" типы.
Я соглашусь с Вами если вы устраните эту ошибку не подключая DLL динамически. И незабудьте рассказать как Вы это сделали.
З.Ы. или эта ошибка только у меня и автора сабжа возникает?
Пишу на D7
← →
evvcom © (2005-10-06 11:06) [12]
> Babay © (06.10.05 09:57) [11]
В примере все гладко. XPManifest не юзал, как-то раз попробовал и забыл. Пока и так устраивает. А уж что там manifest делает, без анализа не скажу, а заниматься этим нет ни времени, ни желания.
Я похоже погорячился, адресовав [10] к [9], но в [7] явно кривой подход.
← →
Bel © (2005-10-06 14:14) [13]> GanibalLector © (05.10.05 02:38) [3]
> procedure ShowMyForm(Handle:HWND);stdcall;
> var Frm:TForm;
> begin
> Application.Handle:=Handle;
> Frm:=TForm1.Create(Application);
> try
> Frm.ShowModal;
> finally
> Frm.Release;
> Frm.Free;
> end;
> end;
1. Release здесь совершенно ни к чему, в нем (вернее в сообщении, которое этот метод посылает) уже содержится Free.
2. Перед выходом надо вернуть Application.Handle на место.
PS. Это на случай если автор решит воспользоваться этим кодом.
← →
GrayFace © (2005-10-06 14:30) [14]evvcom © (06.10.05 11:06) [12]
А уж что там manifest делает, без анализа не скажу, а заниматься этим нет ни времени, ни желания.
Он ничего не делает. Только подключает соответствующий ресурс. Все что делается, делается в модулях UxTheme, Themes и в модулях, их использующих. Возможно, еще где-то.
Страницы: 1 вся ветка
Текущий архив: 2005.10.30;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.047 c