PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [Perl] Dynamisches Einbinden von Bibliotheken in einem Namensraum



Rebell
10-10-2006, 19:14
Hallo ihr.

Ich versuche seit einiger Zeit (verzweifelt) in ein objektorientiertes Perl-Programm dynamisch Funktionen nachzuladen.

Leider habe ich zwei Probleme:
a) Das Einbinden von require funktioniert nur bedingt. Wenn ich Bibliotheken via "require" einladen lasse, befinden diese sich nur im Namensraum der jeweiligen einbindenen Klasse.
Wenn also die Klasse "Haupt" das require verwendet, kann ich die Funktionen nicht in der Klasse "Neben" aufrufen. Ein Aufruf mittels "&Haupt::funktion()" klappt zwar, aber nur bedingt, da ich defined(Haupt::funktion()) darauf nicht anwenden kann (ich muss wissen ob die Funktion vorhanden ist).

b) Mit use schaffe ich es nicht, dynamische Pfade anzugeben.

$pfad = "libs/meine_lib.pm";
use $pfad;
Klappt nicht.


Gibt es eine andere Möglichkeit den Vorteil von use (precompiling) und require (dynamik) miteinander zu kombinieren, oder ist das was ich versuche grundsätzlich schlecht?

Ich hatte auch noch eine andere Methode vorgesehen:
c) Ich lade meine Bibliotheken nicht dynamisch, sondern im Hauptprogramm via use. Dann habe ich aber das Problem, dass mir auch dieser Namensraum unbekannt ist. Ein Aufruf aus der Klasse "Neben" mit "&Main::funktion()" schielt ins Leere.


Irgendwelche Ideen?

reneeb
11-10-2006, 07:44
#!/usr/bin/perl

my $module = 'Test::Module';

if($INC{$module}){
print "$module is loaded\n";
}


eval{
"use $module";
};

if($@){
print "Could not load $module!\n";
}


if($INC{$module}){
print "$module is loaded\n";
}

Rebell
11-10-2006, 14:18
Na klar, eval kann ich doch nehmen... klar... Danke :)
Aber ist das nicht unelegant?

sticky bit
11-10-2006, 19:14
Hmm, wie wäre es, wenn du das require weiterhin benutzt und mit Referenzen auf die geladenen Funktionen arbeitest? Brauchst halt ne Methode in deiner Klasse haben die das verwaltet und a) via beliebigen Identifizierer die gewünschte Funktion aufruft und deren Return-Wert weiter gibt oder b) die Referenz zurück gibt, damit auch aus nem anderen Namensraum drauf zugreifen kannst.

Vorteil wäre auch, dass du Fehler wegen falscher Module bzw. fehlender Funktionen so besser abfangen könntest und die entsprechenden Module evtl., wenn du sie irgendwie in deinem Program "registrierst" (also weisst was wo drin ist) auch nur genau dann laden musst wenn du sie brauchst.

Kompliziert wirds IMHO wenn du gar nicht weisst was in den Modulen drin ist, weiss nicht ob man das zu Laufzeit so einfach auslesen kann (ausser in dem man die Modul-Datei parst, was aber eher "dirty" ist)...

reneeb
12-10-2006, 07:48
Ein Block-eval ist ok. Fehlende Module werfen einen Fehler und die Fehlermeldung landet in $@.

Das ist eine saubere Sache...

Rebell
15-10-2006, 20:21
Ähm. Noch ein "Problem":

eval {
"use $module";
};
if (defined(&bp_test)) {
print "definiert<br>";
} else {
print "funktion nicht definiert (bp_test)<br>";
}

Funktioniert bei mir nicht.


funktion nicht definiert (bp_test)

Aber

eval ("use $module");



definiert

funktioniert sehr wohl. Warum?

sticky bit
15-10-2006, 23:35
Schätze mal, weil "use $module"; einfach nur ein Ausdruck ist, der aber nichts macht. Ist zwar gültige Syntax aber sinnlos. Und du gibst dem eval ja den Block, also wird da nichts interpoliert vorher oder so, sondern das einfach so genommen wies ist. Wenn du irgendwo anders in deinen Code "use $module"; schreibst wird dort auch nichts passieren.
Bei eval("use $modul"); hingegen gibst du dem eval einen Ausdruck der vorher ausgewertet wird.