Возможно ли такое создать в DLL?

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Возможно ли такое создать в DLL?

Сообщение AMD » 12.03.2008 15:31:01

Возможно ли такое создать в DLL?

Например из программы вызываю dll file

Из dll вызываю функцию с параметром [путь к файлу на диске]

В dll находидится функция которая рисует диалоговое окно со всеми нужными компонентами извлекает нужные даные на экране из данного файла (к примеру нужную строку текста) и дальше функция передает эту строку главной программе.

Зачем это?
Ну например чтобы тоже самое не писать несколько раз в разных программах - а так написал один раз а используешь сколько надо для разных прог.

А если точнее подумываю например написать нужные программы а вызывать их из OO basic - таким образом программа работает самостоятельно а OO basic передает только результат функции
AMD
постоялец
 
Сообщения: 189
Зарегистрирован: 23.01.2008 22:25:25
Откуда: Кишинев

Сообщение Slavikk » 13.03.2008 15:44:39

Программа и dll имеют разные разделы памяти, разные rtl и т.д. Засунуть LCL окно в dll не получится, а процедуры без проблем - аналогично как и в delphi. Никто не мешает создавать окно на API системы, во время работы программы.

Окно из Delphi dll - можно загрузить без проблем.
Аватара пользователя
Slavikk
постоялец
 
Сообщения: 208
Зарегистрирован: 15.01.2007 22:34:52
Откуда: Из лесов...

Сообщение B4rr4cuda » 13.03.2008 18:53:43

Программа и dll имеют разные разделы памяти, разные rtl и т.д. Засунуть LCL окно в dll не получится, а процедуры без проблем - аналогично как и в delphi. Никто не мешает создавать окно на API системы, во время работы программы.

Я бы не был столь категоричен.
Код: Выделить всё
library project1;

{$mode objfpc}{$H+}

uses
   {$IFDEF UNIX}{$IFDEF UseCThreads}
   cthreads,
   {$ENDIF}{$ENDIF}
   Interfaces, // this includes the LCL widgetset
   Forms
   { you can add units after this }, unit1;

procedure XShowForm; stdcall;
begin
   Application.CreateForm(TForm1,Form1);
   Form1.ShowModal;
end;

function XGetForm:TFormClass;
begin
   Application.CreateForm(TForm1,Form1);
   Result:=TFormClass(Form1);
end;

exports XShowForm,
         XGetForm;

begin
end.

Юнит пустой. Тестировал саму возможность.

А вот код вызова.
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
type TPro=procedure; stdcall;
var hlib:TLibHandle;
    proc:TPro;
begin
hlib:=LoadLibrary('/home/b4rr4/Devel/DC/test/aaas/lib.so');
if hlib<>0 then
proc:=TPro(GetProcAddress(hlib,'XShowForm'));
if proc<>nil then proc;
end;

procedure TForm1.Button2Click(Sender: TObject);
type TPro=function():TFormClass; stdcall;
var hlib:TLibHandle;
     proc:TPro;
     x:TFormClass;
begin
hlib:=LoadLibrary('/home/b4rr4/Devel/DC/test/aaas/lib.so');
if hlib<>0 then
proc:=TPro(GetProcAddress(hlib,'XGetForm'));
if proc<>nil then x:=proc();

TForm1(x).Show;
end;

initialization
  {$I unit1.lrs}

end.

Тут два метода вызова - первый сам показывает окно, второй передает указатель на окно. Как насчет утечек памяти я не проверял.
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Сообщение Slavikk » 14.03.2008 18:02:29

Пардон, признаю свою ошибку. Но всё же в Windows, ShowModal - работает некорректно (только Show).

Я конкретно имел ввиду если в dll засунуть форму с панелью и пытаться контролы с этой панели отображать на панели в своей программе. У меня это не получилось.
Аватара пользователя
Slavikk
постоялец
 
Сообщения: 208
Зарегистрирован: 15.01.2007 22:34:52
Откуда: Из лесов...

Сообщение B4rr4cuda » 14.03.2008 19:14:24

Ты прав. Только что проверил. Переместить контролы действительно не получается. :/
Думаю, только используя интерфейсное апи, можно это сделать.
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Сообщение AMD » 15.03.2008 01:43:49

Slavikk писал(а):Пардон, признаю свою ошибку. Но всё же в Windows, ShowModal - работает некорректно (только Show).

Я конкретно имел ввиду если в dll засунуть форму с панелью и пытаться контролы с этой панели отображать на панели в своей программе. У меня это не получилось.

А если отображать всю панель с контролами?
AMD
постоялец
 
Сообщения: 189
Зарегистрирован: 23.01.2008 22:25:25
Откуда: Кишинев

Сообщение B4rr4cuda » 15.03.2008 04:02:50

Не получится. Стандартными средствами - либо всю форму, либо ничего.
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Сообщение B4rr4cuda » 16.03.2008 08:45:08

Вот такой простенький код (для GTK) позволяет перемещать на форму контролы из подключаемой библиотеки.
Все компоненты расположены на панели, которую и перемещаем.
Предполагаю что виндозная windows.SetParent(...), сработает также.
Примечание: gtk не любит TLabel-ы, просто не отображает их.
Код: Выделить всё
library lclplug;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms,gtk,gdk,glib,Unit1;

function ListLoad(ParentWin:thandle;FileToLoad:pchar;ShowFlags:integer):thandle; stdcall;
begin
  Application.CreateForm(TForm1, Form1);
  gtk_widget_reparent(PGtkWidget(Form1.Panel1.Handle),PGtkWidget(ParentWin));
end;

exports ListLoad;

begin

end.
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Сообщение AMD » 16.03.2008 11:18:37

B4rr4cuda писал(а):Вот такой простенький код (для GTK) позволяет перемещать на форму контролы из подключаемой библиотеки.
Все компоненты расположены на панели, которую и перемещаем.
Предполагаю что виндозная windows.SetParent(...), сработает также.


Так... - инетересно... можешь по подробней обьяснить как все это работает а то не очень понял - обесняй только под линукс - так как ты тестировал
AMD
постоялец
 
Сообщения: 189
Зарегистрирован: 23.01.2008 22:25:25
Откуда: Кишинев

Сообщение FedeX » 16.03.2008 11:21:07

AMD
А зачем именно LCL окно. Это же так не экономно - и к длл и к проге которая его использовать будут линковаться полностью код ЛЦЛ. В итоге и длл и прога будут занимать по метру (а то и больше) места на диске.
Гораздо проще (и по мойму логичней), запихнуть в длл только парсинг файла (который ты там анализируеш) и передавать все данные в какой-нить структуре главной программе. ...Или создавать это окно в длл, но на Win или GTK API не так уж это и сложно, а выглядит солиднее. :wink:
Аватара пользователя
FedeX
постоялец
 
Сообщения: 422
Зарегистрирован: 27.03.2006 09:25:34
Откуда: украина, житомир

Сообщение B4rr4cuda » 16.03.2008 12:05:41

AMD
Ладно по пунктам:
1. Проект -> Создать проект -> Приложение
2. Кидаем на форму панель, а на неё все нужные компоненты, пишем код, тестируем - все как обычно.
3. Проект -> Просмотреть исходный код проекта
Вместо
Код: Выделить всё
program project1;
пишем
Код: Выделить всё
library NameOfProject;

4. В uses добавляем юниты: gtk, gdk, glib
5. Пишем процедурку или функцию создающую форму и перемещающую панель с контролами на панель вызывающего приложения. Получаем что-то типа:
Код: Выделить всё
library NameOfProject;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms,gtk,gdk,glib,Unit1;
procedure Load(ParentWin:thandle); stdcall;
begin
  Application.CreateForm(TForm1, Form1);
gtk_widget_reparent(PGtkWidget(Form1.Panel1.Handle),PGtkWidget(ParentWin));
end;

exports Load;

begin
end.

6. Пишем вызывающую программу:
Код: Выделить всё
uses ... , dynlibs,gtk,glib,gdk;
...
type TPro=procedure (ParentWin:thandle); stdcall;
var Proc:TPro;
       Hlib:TLibHandle;
       lst:PGList;

...
Hlib:=LoadLibrary('путь к библиотеке');
   if Hlib<>0 then
     begin
       proc:=TPro(GetProcAddress(HLib,'Load'));
       if proc <> nil then
         begin
         {тк lcl панель - это по сути gtk_container и GBox расположенный на нем, то скрываем чайлд компонент и отображаем на его месте свою панель}
       lst:=gtk_container_children(GTK_CONTAINER(PGtkwidget(pnlParent.Handle)));
           if lst<>nil then
              gtk_widget_hide(PGtkWidget(lst^.data));
               
          proc(PnlParent.Handle);
         end;
      end;
....

Вот и все.

2FedeX
Не экономно - это точно, зато удобно. Лично меня от чистого интерфейсного апи тошнит (что от винапи, что от gtk, надо ещё qt попробовать). А вот смесь, позволяющая вытворять трюки и добавляющая гибкости - самое оно. Если размер не критичен, а время поджимает - такие трюки помогают.
А писать на чистом апи, чтобы выглядеть солиднее... пффф, это, простите, детство.
Насчет этого:
Гораздо проще (и по мойму логичней), запихнуть в длл только парсинг файла (который ты там анализируеш) и передавать все данные в какой-нить структуре главной программе.
полностью согласен.
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Re:

Сообщение the_beginer » 13.06.2008 11:08:29

FedeX писал(а):AMD
Гораздо проще (и по мойму логичней), запихнуть в длл только парсинг файла (который ты там анализируеш) и передавать все данные в какой-нить структуре главной программе. ...Или создавать это окно в длл, но на Win или GTK API не так уж это и сложно, а выглядит солиднее. :wink:


а можно пример в студию ?

интересна реализация
the_beginer
новенький
 
Сообщения: 30
Зарегистрирован: 29.05.2008 16:51:51

Re:

Сообщение minoshi » 13.06.2008 15:27:26

[quote="B4rr4cuda"]AMD
Ладно по пунктам:
1. Проект -> Создать проект -> Приложение
2. Кидаем на форму панель, а на неё все нужные компоненты, пишем код, тестируем - все как обычно.
3. Проект -> Просмотреть исходный код проекта
Вместо
Код: Выделить всё
program project1;
пишем
Код: Выделить всё
library NameOfProject;

4. В uses добавляем юниты: gtk, gdk, glib
5. Пишем процедурку или функцию создающую форму и перемещающую панель с контролами на панель вызывающего приложения. Получаем что-то типа:
Код: Выделить всё
library NameOfProject;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms,gtk,gdk,glib,Unit1;
procedure Load(ParentWin:thandle); stdcall;
begin
  Application.CreateForm(TForm1, Form1);
gtk_widget_reparent(PGtkWidget(Form1.Panel1.Handle),PGtkWidget(ParentWin));
end;

exports Load;

begin
end.

6. Пишем вызывающую программу:
Код: Выделить всё
uses ... , dynlibs,gtk,glib,gdk;
...
type TPro=procedure (ParentWin:thandle); stdcall;
var Proc:TPro;
       Hlib:TLibHandle;
       lst:PGList;

...
Hlib:=LoadLibrary('путь к библиотеке');
   if Hlib<>0 then
     begin
       proc:=TPro(GetProcAddress(HLib,'Load'));
       if proc <> nil then
         begin
         {тк lcl панель - это по сути gtk_container и GBox расположенный на нем, то скрываем чайлд компонент и отображаем на его месте свою панель}
       lst:=gtk_container_children(GTK_CONTAINER(PGtkwidget(pnlParent.Handle)));
           if lst<>nil then
              gtk_widget_hide(PGtkWidget(lst^.data));
               
          proc(PnlParent.Handle);
         end;
      end;
....

Вот и все.

а как убить эту панель?
Аватара пользователя
minoshi
постоялец
 
Сообщения: 279
Зарегистрирован: 17.05.2008 21:23:38

Re: Возможно ли такое создать в DLL?

Сообщение B4rr4cuda » 13.06.2008 16:17:58

minoshi писал(а):а как убить эту панель?

gtk_widget_hide(хэндл панели) -чтобы скрыть средствами gtk api.
gtk_widget_destroy(хэндл панели) -чтобы убить средствами gtk api
и Form1.Panel1.free -чтобы убить средствами самого лазаря :).
Неужели трудно было догадаться?
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Re: Возможно ли такое создать в DLL?

Сообщение the_beginer » 13.06.2008 17:31:09

B4rr4cuda писал(а):
minoshi писал(а):а как убить эту панель?

gtk_widget_hide(хэндл панели) -чтобы скрыть средствами gtk api.
gtk_widget_destroy(хэндл панели) -чтобы убить средствами gtk api
и Form1.Panel1.free -чтобы убить средствами самого лазаря :).
Неужели трудно было догадаться?



теперь эту тему можно перенести в раздел FAQ. Это предложение админам, т.к. ресурсы в библиотеке - это может пригодиться каждому.
the_beginer
новенький
 
Сообщения: 30
Зарегистрирован: 29.05.2008 16:51:51

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

Рейтинг@Mail.ru