Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.11.20;
Скачать: CL | DM;

Вниз

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);

сделай так:

var p: pointer;
...
 p:=pointer(Memo);
или можно попробовать (но сам сомневаюсь, тогда в плагине придётся править) p:=Memo.handle;
 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 вся ветка

Текущий архив: 2005.11.20;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.048 c
3-1128951085
MakNik
2005-10-10 17:31
2005.11.20
похоже на блокировку таблиц....?...


1-1130426986
Katya210
2005-10-27 19:29
2005.11.20
Как в WebBrousere


2-1131189872
Kostafey
2005-11-05 14:24
2005.11.20
Программа то работает, то не работает на разных PC


2-1131205639
zero-g
2005-11-05 18:47
2005.11.20
Вопрос по Image


2-1131083532
Gia
2005-11-04 08:52
2005.11.20
DBEdit