Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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);

сделай так:

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 вся ветка

Форум: "KOL";
Текущий архив: 2005.11.20;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.038 c
8-1119852046
Chaser
2005-06-27 10:00
2005.11.20
Подскажите как качественно уменьшить размер картинки


1-1130335504
BobbyDigital
2005-10-26 18:05
2005.11.20
"..." в пути к файлу


2-1130756029
Spectre_s
2005-10-31 13:53
2005.11.20
Параметры


11-1093729013
Sormy
2004-08-29 01:36
2005.11.20
Delphi 7.0 Вылетает...


10-1107741402
Сергей Александров
2005-02-07 04:56
2005.11.20
COM Server&amp;Client (почти по Тенцеру)





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский