Форум: "KOL";
Текущий архив: 2005.11.20;
Скачать: [xml.tar.bz2];
ВнизKol и DLL (Плагины) Найти похожие ветки
← →
stals © (2005-03-09 20:21) [0]Народ! Почему это глючит:
{=== Код основной программы ============================}program Primer;
uses
Windows,
KOL;
var
Form, But1, Memo : PControl;
procedure PlugClick(FileName:string);
var
PlugExec : function(Memo:Pcontrol; fn:string): boolean;
PlugType : function: PChar;
handle : Thandle;
begin
handle := LoadLibrary(Pchar(FileName));
if handle <> 0 then
begin
@plugExec := GetProcAddress(handle,"PluginExec");
@plugType := GetProcAddress(handle,"PluginType");
if PlugType = "RE" then PlugExec(Memo,filename);
end;
FreeLibrary(handle);
end;
procedure ClickBut1( Dummy : Pointer; Sender: PControl );
begin
PlugClick("MyDLL.dll");
end;
begin
form:=NewForm(Applet,"New Project");
Form.Width:=490;
Form.Height:=290;
but1:=NewButton(form,"Load procedure from DLL").SetAlign(caBottom);
but1.OnClick:=TOnEvent(MakeMethod( nil, @clickbut1));
Memo:=NewEditbox(Form,[eoMultiline]).SetAlign(caClient);
run(form);
end.
{=== Код вызываемой DLL ============================================}library MyDLL;
uses
windows, KOL, Messages;
function PluginType : Pchar;
begin
Plugintype := "RE";
end;
function PluginName:Pchar;
begin
PluginName := "My Plagin";
end;
function PluginExec(M:PControl; path:string):Boolean;
begin
m.Color:=clBlack;
m.font.Color:=clWhite;
m.Add("path = "+path);
Result:=true;
end;
exports
PluginType, PluginName, PluginExec;
end.
{==================================================================}
Все ведь, вроде как, правильно?
Но стоит применить этот плагин, так потом, при закрытии проги,
выскакивает error 206.
Если применить его 2 раза подряд, то тоже выскочит! :(
Как лечить?
Если не пытаться изменять параметры Memo в плагине, то все пучком...
А иначе - глюк... :(
Создается впечатление что Pcontrol нельзя применять в качестве передаваемого
параметра функции, ибо с другими объектами такого глюка нет...
Так в чем же, на самом деле, дело? :)
← →
BelchonokH (2005-03-09 20:28) [1]Бегло: Вроде как вместо стринга лучше PChar использовать
← →
stals © (2005-03-09 20:56) [2]BelchonokH:
Один фиг, поменял все string на pchar - та же проблема...
← →
BelchonokH (2005-03-09 21:19) [3]Ну это не было решением самого вопроса... Думаю библиотека про закрытии как-то влияет на твой контрол (может убивает), попробуй так:
function PluginExec(M:Pointer; path:string):Boolean;
var D:PControl;
begin
D:=PControl(M);
D.Color:=clBlack;
D.font.Color:=clWhite;
D.Add("path = "+path);
D:=nil;
Result:=true;
end;
Не пробовал, не знаю, ничего не гарантирую :)
← →
stals © (2005-03-09 22:09) [4]Не-а :(
← →
ECM © (2005-03-09 22:52) [5]Навскидку:
- все равно стринги используются (косвенно).
- поэтому необходимо и в приложении и в длл использовать,
специальный диспетчер памяти ShareMem.
← →
SPeller © (2005-03-10 00:33) [6]ECM © (09.03.05 22:52) [5]
Навскидку:
- все равно стринги используются (косвенно).
- поэтому необходимо и в приложении и в длл использовать,
специальный диспетчер памяти ShareMem.
В программах да. Имелось ввиду, что при передаче параметров использовать PChar вместо string.
← →
z007 (2005-03-10 00:57) [7]Строки действительно используются.
Еще, видимо, что-то не так с Font"ом.
Если PluginExec переписать на api, то, кажется, все работает.
← →
BelchonokH (2005-03-10 07:02) [8]2 stals
Попробуй вызывать тоже по другому, вместоif PlugType = "RE" then PlugExec(Memo,filename);
сделай так:или можно попробовать (но сам сомневаюсь, тогда в плагине придётся править) p:=Memo.handle;
var p: pointer;
...
p:=pointer(Memo);
if PlugType = "RE" then PlugExec(p,filename);
p:=nil;
← →
ECM © (2005-03-10 08:46) [9]SPeller © (10.03.05 00:33) [6]
В программах да. Имелось ввиду, что при передаче параметров использовать PChar вместо string.
M -> PControl из основного приложения (там свой менеджер памяти)
D:=PControl(M);
D.Color:=clBlack;
D.font.Color:=clWhite;
D.Add("path = "+path); // Здесь происходит обращение к менеджеру
памяти из ДЛЛ (промежуточный результат через String), а результат передается в основную программу - которая не сможет
правильно освободить память.
← →
SPeller © (2005-03-10 08:57) [10]ECM © (10.03.05 8:46) [9]
А это уже другой вопрос. Здесь нужно делать по тому же принципу, как и в WInApi (за редкими исключениями) - вызывающая программа должна выделить буфер, в который вызываемая подпрограмма запишет свои данные. Так же и тут со строками надо поступать - передавать указатель на буфер. ПРимерно так:
вместоif PlugType = "RE" then PlugExec(Memo,filename);
надоvar
Buf: PChar;
begin
...
GetMem(Buf, 100);
PlugType(Buf);
if (Buf = "RE") then
...
Что же касается предачи в ДЛЛ объектов - http://delphimaster.net/view/11-1106395918/
← →
SPeller © (2005-03-10 08:59) [11]
GetMem(Buf, 100);
PlugType(Buf);
if (Buf = "RE") then begin
...
end;
FreeMem(Buf);
← →
ECM © (2005-03-10 09:13) [12]2SPeller © (10.03.05 08:57) [10],[11]
С этим я полностью согласен.
Я предлагал попробовать обойтись общим
менеджером памяти - ShareMem или HeapMM (не getmem.inc!)
2Stals: Пробовали ShareMem? - его надо обьявить первым в uses-ах
проектов приложения и длл.
← →
stals © (2005-03-10 11:36) [13]Смотрите, если сделать отчистку, то работает, но так неприкольно...
procedure PlugClick(FileName:string);
var
PlugExec : function(Memo:Pcontrol; fn:string): boolean;
PlugType : function: PChar;
handle : Thandle;
begin
handle := LoadLibrary(Pchar(FileName));
if handle <> 0 then
begin
Memo.clear;
@plugExec := GetProcAddress(handle,"PluginExec");
@plugType := GetProcAddress(handle,"PluginType");
if PlugType = "RE" then PlugExec(Memo,filename);
end;
FreeLibrary(handle);
end;
Видать ему нужен "чистый" Pcontrol :)
← →
stals © (2005-03-10 11:36) [14]Смотрите, если сделать отчистку, то работает, но так неприкольно...
procedure PlugClick(FileName:string);
var
PlugExec : function(Memo:Pcontrol; fn:string): boolean;
PlugType : function: PChar;
handle : Thandle;
begin
handle := LoadLibrary(Pchar(FileName));
if handle <> 0 then
begin
Memo.clear; // Вот это
@plugExec := GetProcAddress(handle,"PluginExec");
@plugType := GetProcAddress(handle,"PluginType");
if PlugType = "RE" then PlugExec(Memo,filename);
end;
FreeLibrary(handle);
end;
Видать ему нужен "чистый" Pcontrol :)
← →
stals © (2005-03-10 12:15) [15]2 z007:
А можно посмотреть вашу реализацию?
2 BelchonokH :
Не получается... :( :)
2 ECM :
Получаеться, все работает после "2Stals: Пробовали ShareMem? - его надо обьявить первым в uses-ах проектов приложения и длл."
Но после закрытия программы все равно выскакивает!
Я чувстыую, развязка близка... :)
← →
ECM © (2005-03-10 12:31) [16]{=== Код основной программы ============================}
program Primer;
uses
ShareMem,
Windows,
KOL;
var
Form, But1, Memo : PControl;
PlugExec : function(Memo:Pcontrol; fn:string): boolean = nil;
PlugType : function: PChar = nil;
handle : Thandle;
procedure PlugClick(FileName:string);
begin
if Assigned(PlugType) and Assigned(PlugExec) then
if (PlugType = "RE") then PlugExec(Memo,filename);
end;
procedure ClickBut1( Dummy : Pointer; Sender: PControl );
begin
PlugClick("MyDLL.dll");
end;
begin
form:=NewForm(Applet,"New Project");
Form.Width:=490;
Form.Height:=290;
but1:=NewButton(form,"Load procedure from DLL").SetAlign(caBottom);
but1.OnClick:=TOnEvent(MakeMethod( nil, @clickbut1));
Memo:=NewEditbox(Form,[eoMultiline]).SetAlign(caClient);
handle := LoadLibrary("MyDLL.dll");
if handle <> 0 then
begin
@plugExec := GetProcAddress(handle,"PluginExec");
@plugType := GetProcAddress(handle,"PluginType");
end;
run(form);
FreeLibrary(handle);
end.
{=== Код вызываемой DLL ============================================}library MyDLL;
uses
ShareMem, windows, KOL, Messages;
function PluginType : Pchar;
begin
Plugintype := "RE";
end;
function PluginName:Pchar;
begin
PluginName := "My Plagin";
end;
function PluginExec(M:PControl; path:string):Boolean;
begin
m.Color:=clBlack;
m.font.Color:=clWhite;
m.Add("path = "+path);
Result:=true;
end;
exports
PluginType, PluginName, PluginExec;
end.
И ничего не глючит :)
← →
ECM © (2005-03-10 12:41) [17]Тут два момента:
1) ShareMem в обоих - позволяет "не заботится" о выделении памяти;
2) Но до тех пор пока плагин не выгружен - выгрузка -> память
выделенная в плагине освободилась. (То что сразу после выгрузки ДЛЛ не падает - еще не показатель - просто память от ДЛЛ-ки
не сразу отдается системе. Memo.Clear - это из той же области)
Лучше все-таки применять способ описанный SPeller [10],[11]
т.е. выделение памяти должен контролировать кто-то один.
Тогда можно и плагины смело загружать-выгружать - а иначе
проблема вылезет где-нибудь в другом месте.
← →
stals © (2005-03-12 17:00) [18]2 ECM
А все равно при закрытии выскакивет... :)
Halt по Form.OnClose спасает, это приемлимо?
Но хотя б так! Офигительное Спасибо... :)
← →
bar (2005-03-24 10:57) [19]Используй интерфейсы. Вот пример.
library Calc32;
uses
KOL,USHare;
{$R *.res}
type
TIterfac=class(TInterfacedObject,ICalc)
FTemp: integer;
public
constructor Create;
destructor Destroy; override;
function Execute(const Show: boolean): integer;
procedure Prepare;stdcall;
end;
constructor TIterfac.Create;
begin
inherited;
// ShowMessage(int2str(INteger(self))+": Created"); // for test
end;
destructor TIterfac.Destroy;
begin
// ShowMessage(int2str(INteger(self))+": Destroy");// for test
inherited;
end;
function TIterfac.Execute(const Show: boolean): integer;
begin
inc(FTemp);
if Show then ShowMessage(int2str(Ftemp));
end;
procedure TIterfac.Prepare;
begin
FTemp:=0;
end;
function CreateCalcObject: ICalc; export; stdcall;
begin
result := TIterfac.create as ICalc;
end;
exports CreateCalcObject;
begin
end.
Модуль с интерфейсом:
unit UShare;
interface
type
ICalc=interface
["{0B9C4636-83A0-4345-8D65-8F59F46E9CC2}"]
function Execute(const Show: boolean): integer;
procedure Prepare;stdcall;
end;
implementation
end.
И кусок из проекта. Пример использования.
function CreateCalcObject: ICalc;stdcall; external "Calc32.dll" name
"CreateCalcObject";
implementation
var I:ICalc;
{$IFNDEF KOL_MCK} {$R *.DFM} {$ENDIF}
{$IFDEF KOL_MCK}
{$I Unit1_1.inc}
{$ENDIF}
procedure TForm1.Button1Click(Sender: PObj);
begin
I :=CreateCalcObject; // Создаем интрефейс
I.Prepare;
end;
procedure TForm1.Button2Click(Sender: PObj);
begin
I := nil; // Освобождаем интерфейс
end;
procedure TForm1.Button3Click(Sender: PObj);
begin
I.Execute(true);
end;
Освобождать интерфейс самому по-моему не обязательно, т.к. при закрытии приложения он
освобождается сам.
При использовании динамической загрузки dll-ки (LoadLibrary) могут быть проблемы с
выгрузкой билиотеки. Нужно следить за тем, чтобы все указатели на интерфейс были
освобождены (:=nil) до выгрузки дллки из памяти.
← →
Barloggg (2005-03-24 12:45) [20]один вопрос: эта ошибка появляется при закрытии программы запущенной из под дельфи или при запуске отдельно стоящего ехе-файла?
При работе с DirectX и запуске из под дельфей глючила следующая строка
if D3D<>nil then
D3D._release;//эта строка проходит
D3D:=nil;//эта глючит
end;
хе-хе... в чем прикол я так и не понял...
Поэтому я запускал готовый ехе-шник...
а при запуске из под дельфи вообще не производил освобождение памяти. точнее просто отцеплял и забивал на это.
так что может быть и тебе забить если ехе-шник явной ошибки не выдает.
← →
stals © (2005-03-28 03:10) [21]Barloggg
Теперь все в порядке... :)
Сначала по OnClose Делел Halt, затем,
Как-то попробовал убрать его и все пропало...
Вот такие вот странные дела... :-/
Если честно, то так и не понял, что это было... :)
Страницы: 1 вся ветка
Форум: "KOL";
Текущий архив: 2005.11.20;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.071 c