AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

einfaches plugin-system

Ein Thema von theomega · begonnen am 23. Jul 2002 · letzter Beitrag vom 24. Jul 2002
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von theomega
theomega

Registriert seit: 18. Jun 2002
684 Beiträge
 
#1

einfaches plugin-system

  Alt 23. Jul 2002, 14:49
Hallo
ich bräuchte ein Pluginsystem, wo jedes Plugin nur eine einfache Funktion beinhaltet, die einen String zurückgibt.

Hat jemand ein einfaches Beispiel, Code, Tips??

Tnxs

the OmeGa
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 
#2
  Alt 23. Jul 2002, 14:51
Ich bin mir ja nicht sicher, was Du erreichen willst, aber das hört sich nach einem typischen DLL Problem an. Das heisst, alle Plugins liegen als DLL vor und werden vom Programm "on-demand" geladen.

Wenn es das ist, dann ist es eigentlich recht einfach.



P.S. Unter Umständen reicht eine INI Datei (oder mehrere)...
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
Benutzerbild von theomega
theomega

Registriert seit: 18. Jun 2002
684 Beiträge
 
#3
  Alt 23. Jul 2002, 14:56
nein, eine INI-Datei reicht nicht, weil die Plugins verschiedene Daten zurückgeben(u.a. aus dem Internet, aus dem Netzwerk, Bios, Hardware)

Aber sonst müßte das mit einfachen DLLs schon gehen. Hat jemand (hast du) ein Beispiel???? Tip?
  Mit Zitat antworten Zitat
Daniel
(Co-Admin)

Registriert seit: 30. Mai 2002
Ort: Hamburg
13.920 Beiträge
 
Delphi 10.4 Sydney
 
#4
  Alt 23. Jul 2002, 15:10
Beispiel habe ich keines; dafür aber einen Tipp:
Deine Anwendung könnte sich aus Deinem PlugIn-Verzeichnis alle DLL's herauslesen ("FindFirst" / "FindNext"), jede dieser Bibliotheken laden und mittels "GetProcAddress" herausfinden, ob die aktuell geladene Bibliothek eine von Dir definierte Prozedur exportiert. (Mehr zu GetProcAddress in der MSDN-Bibliothek unter http://msdn.microsoft.com/library/de...c/dll_0f8z.asp).

Grüße,
Daniel
Daniel R. Wolf
  Mit Zitat antworten Zitat
Benutzerbild von theomega
theomega

Registriert seit: 18. Jun 2002
684 Beiträge
 
#5
  Alt 23. Jul 2002, 16:15
Das blick ich jetzt nicht
  Mit Zitat antworten Zitat
MathiasSimmack
(Gast)

n/a Beiträge
 
#6
  Alt 23. Jul 2002, 16:49
Du schreibst eine Funktion, wie etwa:
Code:
function IchBinEinPlugin: boolean;
begin
  MessageBox(0,'Da bin ich!','Plugin',
    MB_OK or MB_ICONINFORMATION);

  Result := true;
end;
Da es sich um eine DLL handelt, musst du dafür sorgen, dass diese Funktion auch exportiert wird. (Wie, steht in der Delphi-Hilfe.) Mir ist jetzt nichts Besseres eingefallen; aber bei einer Funktion sollte man noch irgendwas machen, dass den Rückgabewert rechtfertigt. Es kann also auch eine Prozedur sein.

Der Rest ist dynamisches Laden von DLL-Prozeduren und -Funktionen. Beispielsweise so:
Code:
type
  // diese Deklaration MUSS der Deklaration der
  // DLL-Funktion entsprechen!!!
  // In diesem Fall ist es also eine Funktion mit
  // Bool-Rückgabewert
  TDllFunc = function: boolean;
var
  MeineDll : dword = 0;
  DllFunc : TDllFunc;

{ ... }

MeineDll := LoadLibrary('plugin.dll');
if(MeineDll <> 0) then
  begin
     // hier wird versucht, die Funktion "IchBinEinPlugin"
     // (s. erstes Code-Beispiel) zu laden
     DllFunc := GetProcAddress(MeineDll,'IchBinEinPlugin');

     // geht nicht, dann ist´s auch kein Plugin von dir
     if(@DllFunc = nil) then
       begin
          FreeLibrary(MeineDll); MeineDll := 0;
       end;
  end;

{ ... } // irgendwas machen

// am Programmende immer die DLL(s) freigeben
if(MeineDll <> 0) then
  FreeLibrary(MeineDll);
So, ich hoffe, dass ich jetzt keine groben Schnitzer gemacht habe (vielleicht Schreibfehler), aber so sähe das Prinzip mit GetProcAddress aus. Bei all deinen Plugins solltest du immer den gleichen Funktionsnamen benutzen - in dem Fall also "IchBinEinPlugin" - damit dein Programm nur die korrekten DLLs lädt.

Wenn das Laden also geklappt hat, kann dein Programm die Plugin-Funktion aufrufen, was eine Dialogbox mit der Meldung "Da bin ich" zur Folge haben sollte.

Habe ich was vergessen, Leute?
  Mit Zitat antworten Zitat
Benutzerbild von theomega
theomega

Registriert seit: 18. Jun 2002
684 Beiträge
 
#7
  Alt 23. Jul 2002, 17:40
passt genau, für nachmacher den Tip: die funktionen in der DLL dürfen als rückgabewert keinen String enthalten, stattdessen pchar verwenden.
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 
#8
  Alt 23. Jul 2002, 22:06
Zitat von theomega:
passt genau, für nachmacher den Tip: die funktionen in der DLL dürfen als rückgabewert keinen String enthalten, stattdessen pchar verwenden.
Schlichtweg falsch, Du darfst Strings zurückgeben, sofern Du unter Delphi bleibts, Du musst jedoch die unit ShareMem einbinden. Richtig: Es empfiehlt sich auf Strings in Funktionen und Prozeduren zu verzichten. Das ist ein gewaltiger Unterschied
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
MathiasSimmack
(Gast)

n/a Beiträge
 
#9
  Alt 24. Jul 2002, 08:08
Ich habe mal die unendlichen Weiten meiner HD durchwühlt und folgendes Beispiel eines Plugins gefunden, was IMHO richtig interessant ist und als Ansatzpunkt für eigene Dinge benutzt werden kann. (Ich wusste doch, dass ich so was rumliegen habe.) Das Beispiel stammt von William Yang. Ich habe - soweit ich´s für erforderlich hielt - Kommentare eingesetzt. Ansonsten ist aber nichts verändert!


1. Das Programm, dass die Plugins lädt, exportiert selbst eine Funktion, die den ausgewählten Text eines Memos ändert. Das Folgende steht im Projektquelltext (*.dpr):
Code:
procedure ReplaceText(Text: PChar); far;
begin
  Form1.Memo1.SelText := StrPas(Text);
end;

exports ReplaceText;

2. Die Plugin-DLL besteht nur aus den paar Zeilen:
Code:
library First;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  View-Project Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the DELPHIMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using DELPHIMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses
  SysUtils,
  Classes,
  Windows;

type
  //Turn the optimize and huge string option off
  //if Delphi cannot compile your plugin
  // you will see when your have some compilicated typecasts
  iReplace = procedure (Text: PChar);

var
  OwnerApp: Integer;


function GetName: Pchar; far;
begin
  // Das ist der Eintrag, der später im Menü des Hauptprogramms
  // stehen wird
  Result := '&First Test';
end;


// hier ruft die DLL die "ReplaceText"-Funktion aus dem Hauptprogramm
// auf und ersetzt den ausgewählten Text im Memo durch einen fixen
// Text
procedure InsertText; far;
begin
  iReplace(GetProcAddress(OwnerApp, 'ReplaceText'))('Magic Plugins');
end;

procedure Init(Owner: Integer); far
begin
  OwnerAPP := Owner;
end;

exports
  GetName, InsertText, Init;

begin
end.

3. Im Formularcode wird jetzt ein solches Plugin geladen und in eine eigene Klasse geschrieben. Bevor ihr loslegt: ihr braucht noch ein Memo und ein Hauptmenü mit dem Eintrag "Plugin". Vorhanden? Dann kommt das:

[code:1:68de408964]var
Plugins: TList;

type
//plug in object
TTestPlugIn = class
Name: String;
Address: Integer;
Call: Pointer;
end;

//type cast of plug in functions
GetNameFunction = function : PChar;
InserText = procedure;
//HInstance is the application's histance, send it to the
//plugin so it can use the exports function from here.
PlugInInit = procedure (Owner: Integer);

var
StopSearch : boolean;

// btw: noch eine Variante zum Dateiensuchen ;o)
procedure SearchFileExt(const Dir, Ext: String; Files: TStrings);
var
Found: TSearchRec;
Sub: String;
i : Integer;
Dirs: TStrings; //Store sub-directories
Finished : Integer; //Result of Finding
begin
StopSearch := False;
Dirs := TStringList.Create;
Finished := FindFirst(Dir + '*.*', 63, Found);
while (Finished = 0) and not (StopSearch) do
begin
//Check if the name is valid.
if (Found.Name[1] <> '.') then
begin
//Check if file is a directory
  Mit Zitat antworten Zitat
Benutzerbild von theomega
theomega

Registriert seit: 18. Jun 2002
684 Beiträge
 
#10
  Alt 24. Jul 2002, 11:25
Das ist jetzt schon wesentlich komplizierter. Aber ich habe es mit MathiasSimmack's Tip hinbekommen. Aber aus irgendeinem Grund nur mit PChar. Bei Strings gab es einen laufzeitfehler, tortz eingebundener sharemem.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:37 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz