Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Проблемс с плагинами


Автор: AlexeyShestchenko 19.2.2008, 05:00
Понадобилось прикрутить к приложению плагины для возможности разширения функционала.
Сначала опишу задачу, потом о проблеме.
Т.к. мне не нужна загрузка плагинов при создании формы, то список плагинов находится в файле и загружается stringlist;
В каждом плагине должно быть по 1-3 функции, все они работают с текстом который получают(должны получать) из программы и возращают обработанный вариант в memo. Функции все готовы осталось только организовать работу с плагинами.
В edit программы пишется название плагина через пробел текст и параметры обработки.
Поскитался по инету в надежде найти исходники и примеры по работе с плагинами,но они что-то все плохо рабочие.
Например:
Код

var
      Form1: TForm1;
      GetSimpleText: function(LangRus: Boolean): PChar;
      LibHandle: THandle;

procedure Button1Click(Sender: TObject);
begin
  {"Чистим" адрес функции от "грязи"}
  @GetSimpleText := nil;
  {Пытаемся загрузить библиотеку}
  LibHandle := LoadLibrary('MYDLL.DLL');
  {Если все OK}
  if LibHandle >= 32 then begin
    {...то пытаемся получить адрес функции в библиотеке}
    @GetSimpleText := GetProcAddress(LibHandle,'GetSimpleText');
    {Если и здесь все OK}
    if @GetSimpleText <> nil then
      {...то вызываем эту функцию и показываем результат}
      ShowMessage(StrPas(GetSimpleText(True)));
  end;
  {И не забываем освободить память и выгрузить DLL}
  FreeLibrary(LibHandle);
end;


и Dll:
Код

library mydll;

uses SysUtils, Classes;

{Определяем функцию как stdcall}
function GetSimpleText(LangRus: Boolean): PChar; stdcall;
begin
  {В зависимости от LangRus возвращаем русскую (True) либо английскую (False) фразу}
  if LangRus then
    Result := PChar('Здравствуй, мир!')
  else
    Result := PChar('Hello, world!');
end;

{Директива exports указывает, какие функции будут экспортированы этой DLL}
exports GetSimpleText;

begin
end.


после показа мессаги выскакивает в дебаггер :(

Как я понимаю, то программа должна обрабатывать текст взятый из эдита, первое слово будет название плагина,дальше она должна отадавать плагину текст с параметрами обработки, тот в свою очередь обрабатывает и отправляет в memo программы. Нужна возможность указывать вместо текста ссылку на файл,тогда обрабьотка будет занимать некоторое время,знач над делать еще и возможность в потоке.
Помогите разобраться! Буду благодарен!

Автор: Qu1nt 19.2.2008, 11:00
Вот так будет правильней:
Код

  GetSimpleText: function(LangRus: Boolean): PChar; stdcall;

Автор: ivan219 19.2.2008, 15:31
И ещё помойму нужно в uses провисать ShareMem только надо его прописывать не в юнете формы а в файле проекта.
Код

program Project1;

uses
  ShareMem, Forms,
  Unit1 in 'Unit1.pas' {Form1};

Автор: AlexeyShestchenko 19.2.2008, 17:03
Цитата(ivan219 @ 19.2.2008,  15:31)
И ещё помойму нужно в uses провисать ShareMem только надо его прописывать не в юнете формы а в файле проекта.
Код

program Project1;

uses
  ShareMem, Forms,
  Unit1 in 'Unit1.pas' {Form1};

с использованием sharemem вылетает ошибка на выхохе,чето там invalid pointer

Автор: Qu1nt 19.2.2008, 18:51
Мой вариант не работает?

Автор: AlexeyShestchenko 19.2.2008, 18:57
Цитата(Qu1nt @ 19.2.2008,  18:51)
Мой вариант не работает?

твой работает,спасибо!

Автор: Rennigth 19.2.2008, 18:57
Цитата(ivan219 @  19.2.2008,  15:31 Найти цитируемый пост)
И ещё помойму нужно в uses провисать ShareMem

Это для использования стрингов.

Автор: AlexeyShestchenko 19.2.2008, 19:58
function GetText(Text:String): PChar; stdcall;
var
  i:integer;
begin
  for i:=0 to 20 do
  Result := PChar(text+inttostr(i));
end;


эта функция возращает text+20

а мне надо чтобы возращала все от 0 до 20,как сделать?

Автор: THandle 19.2.2008, 20:37
AlexeyShestchenko, так пойдет?
Код


function GetText(Text:String): PChar; stdcall;
var
  i:integer;
begin
  result := nil;
  for i:=0 to 20 do
    Result := PChar(Result + text + inttostr(i));
end;

Автор: AlexeyShestchenko 19.2.2008, 21:01
спасибо, это я для теста сделал простой алгоритм, а если там довольно тяжелоемкий анализ и результаты будут не сразу,хотелось бы чтобы по мере получения одного из результов они уже появлялись в результе и я мог видеть это дело у себя в программе в memo!

Автор: aktuba 19.2.2008, 22:07
AlexeyShestchenko, используй WideString и забудь о PChar... И никаких дополнений в uses прописывать не надо.

Автор: source777 19.2.2008, 22:46
Цитата(AlexeyShestchenko @  19.2.2008,  21:01 Найти цитируемый пост)
хотелось бы чтобы по мере получения одного из результов они уже появлялись в результе и я мог видеть это дело у себя в программе в memo!
Для этого, по хорошему, надо вынести цикл из dll в главную программу, а в dll оставить тело цикла, которое будет на каждой итерации возвращать текущее значение...

Автор: AlexeyShestchenko 19.2.2008, 22:47
спасибо, но предыдущую тему не могу решить

Автор: remax 19.2.2008, 22:59
JEDI VCL - фореве!

Там есть готовая реализация механизма плагинов и 5 (!)  работающих примеров. Охватываю самые разные варианты реализации.


Насчет ShareMem: обсуждалось на форуме, например - 
http://forum.vingrad.ru/faq/topic-157676.html

Автор: AlexeyShestchenko 19.2.2008, 23:31
JEDI VCL, чет не нашел там примера по плагинам...
может не то скачал....


source777, 

вот для примера решил засунуть в длл idicmpclient, длл принимает хост и начинает пинговать его. Разумеется в главное приложение должен приходить ответ о том как дошли пакеты.
пишу в длл:
Код

function IdIcmpClient1Reply:WideString;
var
  AReplyStatus: TReplyStatus;
begin
  Result := IntToStr(AReplyStatus.SequenceId); //получаем результат
end;

// сам пинг
function ping(host:string):Boolean;
begin
Result := False;
  if host = '213.180.204.8' then
  begin
    IdIcmpClient1 := TIdIcmpClient.Create(nil);
    IdIcmpClient1.Host := host;
    IdIcmpClient1.ReceiveTimeout := 2000;
    IdIcmpClient1.Ping;
    Result := True;
    IdIcmpClient1.Free;
  end;
end;

function GetText(Text:String): WideString; stdcall;
begin
if ping(Text) then
  Result := idIcmpClient1Reply
  else
  Result := 'no';
end;


вроде правильно возращает результат,но если нажимать дальше на кнопку,то будет добавляться одно и тоже значение почему?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)