Schrift
[thread]6375[/thread]

PlugIns mit realisieren...: ins Verzeichnis packen und lööpt... (Seite 2)



<< |< 1 2 3 >| >> 26 Einträge, 3 Seiten
esskar
 2004-07-06 04:40
#83843 #83843
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
ich würde das ganze in ein OO-Interface zwingen!
z.B.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package PluginInterface;

sub new(...) { ... }

sub get_name() { .. }

sub get_menu() { ... }

sub on_click() { ... }

sub show() { ... }

# ... etcpp.

1;


wobei dann die Funktionen des PluginInterface nur dummy werte zurück geben...
und dann implemnetieren deine Plugins einfach genau das interface und fertig ist...
ist meiner meinung nach eine gute und saubere lösung
kabel
 2004-07-06 14:46
#83844 #83844
User since
2003-08-04
704 Artikel
BenutzerIn
[default_avatar]
du meinst also vererbung einer abstrakten pluginklasse?
note_to_myself: muss den schoenen artikel ueber plugins noch fertiglesen ...
-- stefan
esskar
 2004-07-06 17:54
#83845 #83845
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
genau...
gelesen hab ich die artikel auch nicht...
aber so würde ich es z.B. in C++ oder Java machen...
auch die unter Windows bekannten COM Dlls sind so aufgebaut!
Gast Gast
 2004-07-06 18:19
#83846 #83846
[quote=esskar,06.07.2004, 02:40]ich würde das ganze in ein OO-Interface zwingen!
z.B.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package PluginInterface;

sub new(...) { ... }

sub get_name() { .. }

sub get_menu() { ... }

sub on_click() { ... }

sub show() { ... }

# ... etcpp.

1;


wobei dann die Funktionen des PluginInterface nur dummy werte zurück geben...
und dann implemnetieren deine Plugins einfach genau das interface und fertig ist...
ist meiner meinung nach eine gute und saubere lösung[/quote]
Hab's mal mit einem bestehenden Programm probiert ...
funktioniert einwandfrei wenn dem Event-Handler des Hauptprogramms, die Event-Handler des jeweiligen PlugIn (Moduls) hinzugefügt werden (aus dem jeweiligen PlugIn-Modul heraus als Rückgabe-Hash).
renee
 2004-07-06 18:26
#83847 #83847
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
@Dieter: Würde mich interessieren, wie Du das genau gemacht hast. Kannst Du mal etwas Code posten...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
sri
 2004-07-06 18:33
#83848 #83848
User since
2004-01-29
828 Artikel
BenutzerIn
[Homepage] [default_avatar]
Bei POE findest du massenhaft Beispiele für gelungene Plugin APIs, heissen da nur anders. ;)

Die beste API hat für mich aber immernoch Kwiki!
renee
 2004-07-06 18:40
#83849 #83849
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Ok, danke...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Magic
 2004-07-06 19:21
#83850 #83850
User since
2003-09-30
91 Artikel
BenutzerIn
[Homepage] [default_avatar]
Die ganzen Vorschläge die gemacht wurden haben leider (so wie ich das sehe) den grossen Haken, dass der Namensraum des Moduls/Plugins bekannt sein muss, um es anzusprechen, oder das zumindest im Hauptprogramm eine entsprechende Zeile hinzugefügt werden muss, um jeden einzelne PlugIn anzusprechen.

Ich hab in der zwischenzeit mal meine eigene Api zusammengebastelt. Ist noch nicht ganz fertig, sieht aber in etwa so aus:

Das Hauptprgramm, also die API:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
sub GetPluginList{
# array fuer die hashreferenzen auf die plugindaten
my ( @plugins ) = GetPluginFromDir( 'plugins', '1' );

my $i;
for my $plugin ( @plugins ){
$i++;
print "\n Name: ".$plugin->{pluginname};
print "\n Version: ".$plugin->{version};

my $ref = $plugin->{'funktionen'};

for( keys %$ref ) {
print "\n Funktion: ".$_;
print "\n -->Rueckgabe: ";
print eval "$plugin->{package}::$_";

}
}
}

sub GetPluginFromDir{
   # uebergeben wird der directory-path
   my $directory = $_[0];

   # die on error
   die 'Not enough arguments to get Plugin.' if ! $directory;

   # ist diese var gesetzt, werden auch unterverzeichnisse
   # bis zu dieser Tiefe mit verarbeitet
   my $tiefe = $_[1];

   # enthaelt und uebergibt den gefunden plugin
   my ( @plugins );

   # die plugindirectory darf fuer jeden plugin
   # ein eigenes verzeichnis mit allen templates
   # etc. enthalten.
   opendir( PLUGINS, $directory ) ||
        die 'Can&acute;t open Plugindirectory: ' . $directory;

   for ( readdir( PLUGINS ) ){
      # es werden nur verzeichnisse und .pl files gelesen.:
      # weiter wenns uebergeordnete verzeichnisse sind
      next if $_ =~ m|^\.+|;

      my $fullpath = $directory . '/' . $_;

      # diese routine rekursiv aufrufen, wenns ein verzeichnis
      # ist und die tiefe mindestens 1 betraegt
      if ( -d $fullpath && $tiefe >= 1 ){
          # resttiefe fuer den naechsten aufruf um 1 tiefer setzen
          my $resttiefe = $tiefe-1;
          push( @plugins, GetPluginFromDir( $fullpath, $resttiefe ) );
      }

      # weiter wenns kein plugin ist
      next if $_ !~ m|\.pl$|i;

      # plugin validieren oder bei fehler einfach ueberspringen
      my $pluginhashref = ValidatePlugin( $fullpath ) || next;

      push( @plugins, $pluginhashref );
   }

   closedir PLUGINS;


   return ( @plugins );
}

# pruefen der gueltigkeit des plugins
sub ValidatePlugin{
   my $fullpath = $_[0];

   my %pluginfo;
   # plugin laden, rueckgabewert des moduls ist der namensraum
   require $fullpath;

   %pluginfo = &PlugIn::init;

   # abbrechen und NULL zurückgeben, wenn nicht
   # die mindestinfos zurueckgeliefert wurden
   return undef if ! $pluginfo{'pluginname'};
   return undef if ! $pluginfo{'version'   };
   return undef if ! $pluginfo{'package'   };
   return undef if ! $pluginfo{'package'   };

   return \%pluginfo;
}


und so sieht etwa ein PlugIn aus:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package PlugIn;
sub init{ &HuhnPlugIN::PluginInfo() }

package HuhnPlugIN;

my $PACKAGE     = 'HuhnPlugIN';
my $PLUGINNAME  = 'HuhnPlugIN';
my $VERSION     = '0.1';

# init() wird nach dem require aufgerufen und gibt den namen,
# die version und einen link zurueck

sub PluginInfo{
   my %link;

   # links werden folgendermassen definiert:
   # der schluessel ist der name der funktion,
   # der wert der link der aufgerufen wird.

   # es koennen beliebig viele funktionen/links
   # deklariert werden.

   $link{ 'TestFunk' } = 'TestFunk';

   # anhaengen des packagenamens an jeden link
   for ( keys %link ){ $_ .= 'plugin=' . $PACKAGE }



   # das hauptprogramm erhaelt die rueckgabewerte
   # und erstellt fuer jeden eintrag im link-hash
   # einen link in der pluginrubrik
   # felder mit einem * sind optional, alle anderen
   # felder muessen vorhanden sein, sonst wird's
   # plugin nicht validiert und fliegt raus
   return( 'pluginname' => $PLUGINNAME,
           'package'    => $PACKAGE,
           'version'    => $VERSION,
           'menubutton' => \%link,
           'folder'     => '',           # *
          );
}



# PLUGIN Funktionen >>

sub TestFunk{
   return "Huhn ist nicht Hase";
}


Ist wie gesagt noch nicht fertig, sondern erst mal ein Grundmodell... aber funktionstüchtig.
Die PlugIns liegen hierbei im Ordner Plugins, entweder direkt da, oder in einem Unterordner, wie mans lieber mag.
Eine registrierung der PlugIns an einer anderen Stelle ist nicht notwendig, was mir sehr wichtig ist.
Nachdem einbinden mit require und Prüfung auf validität, wird die Funktion init() aufgerufen, die in jedem Plugin im Namensraum PlugIn vorhanden ist.
Die Funktion init() ruft eine Funktion im Namensraum des PlugIns auf und liefert den Namensraum des PlugIns, sowie Name, Version und enthaltene Funktionen zurück.

So nun seid Ihr dran ;-) Was gibt's zu meckern? Wo könnt man's verbessern?
Ich bin der Meinung, damit hat man eine gute Mischung aus skalierbarkeit, nutzerfreundlichkeit und eweiterbarkeit, da so einfach Perlprogramme geschrieben und eingebunden werden könne , solang' die (wenigen) Vorgaben beachtet werden.

Gruss
Stefan\n\n

<!--EDIT|Magic|1089129046-->
Ein Weiser gibt nicht die richtigen Antworten, sondern er stellt die richtigen Fragen.
esskar
 2004-07-06 20:04
#83851 #83851
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/perl

use strict;

sub get_class
{
my ($pluginfile) = @_;

$pluginfile =~ m!(.*?)\.pm$!i;

return $1;
}

my $pluginfile = "Plugin.pm";
my $pluginclass = get_class($pluginfile);

require $pluginfile;
my $obj = undef;
eval ($obj = new $pluginclass);

print $obj->get_name() if $obj;

1;


Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package Plugin;

use strict;

sub new
{
my ($parent, %args) = @_;

my $class = ref($parent) || $parent;
my $self = {};

bless $self, $class;

return $self;
}

sub get_name
{
my ($self) = @_;

return "Plugin!";
}

1;


natürlich muss noch errorchecking und inputvalidation rein!
Magic
 2004-07-06 20:23
#83852 #83852
User since
2003-09-30
91 Artikel
BenutzerIn
[Homepage] [default_avatar]
@esskar
Auch nicht schlecht, hat aber wiederum den Haken, dass die ganze Sache nocht lööpt, wenn der Dateiname nen anderer ist als der Namensraum... und sei es nur die Groß-/Kleinschreibung.
Ist also nicht Narrensicher genug :-)
Aber man könnte Deinen Oo Ansatz mit meinem Gewurschtel paaren, wäre vielleicht nicht verkehrt.
Ein Weiser gibt nicht die richtigen Antworten, sondern er stellt die richtigen Fragen.
<< |< 1 2 3 >| >> 26 Einträge, 3 Seiten



View all threads created 2004-07-03 01:11.