# Einbinden von Perl-Code

### Ausführung von externem Code mittels `do()`

Wird die Zahl der Subroutinen in einem Programm immer größer oder verwendet man dieselben (oder ähnliche) Unterprogramme immer wieder in verschiedenen Programmen, so sollte man den Programmcode auf mehrere Dateien verteilen. Es empfiehlt sich, das Hauptprogramm zusammen mit ein paar wichtigen Subroutinen in einer Datei zu speichern (die dann als Perl-Skript ausgeführt wird), und alle anderen Subroutinen (bzw. Klassen bei objekt-orientierter Programmierung) - in logischen Gruppen zusammengefaßt - in eigenen Dateien abzulegen.

Um nun Programmcode aus einer zusätzlichen Datei in ein Hauptprogramm einzubinden, gibt es in Perl verschiedene Möglichkeiten.

Die einfachste ist die Verwendung der Funktion "`do()`". Hiermit wird Programmcode aus einer externen Datei so wie er dort abgelegt ist in das aktuelle Programm (also an die Stelle, wo `do` steht) eingebaut und ausgeführt (so als würde man `eval()` auf den Dateiinhalt anwenden).

Datei `prog.pl`:

    #!/usr/local/bin/perl -w

    print "Erste Zeile des Hauptprogramms\n";
    do "funkt.pl";
    print "Ende des Hauptprogramms\n";

Datei `funkt.pl`:

    print "Ausgabe aus 'funkt.pl'\n";

    Erste Zeile des Hauptprogramms
    Ausgabe aus 'funkt.pl'
    Ende des Hauptprogramms

Wie man sieht, erwartet `do()` als Argument einen Dateinamen. Diese Datei wird dann in allen Verzeichnissen gesucht, die im Array `@INC` aufgelistet sind. Befindet sich die gesuchte Datei in einem Verzeichnis, das nicht standardmäßig zu `@INC` gehört, so kann der Pfad (vor dem Aufruf von `do()`) beispielsweise durch

> `push(@INC,$verzeichnispfad);`

hinzugefügt werden.

Ein Nachteil von `do()` ist die Tatsache, das jedesmal, wenn diese Funktion aufgerufen wird, die entsprechende Datei geöffnet, gelesen und geparst wird, weswegen sich der Einsatz z.B. innerhalb einer oft durchlaufenen Schleife nicht gerade empfiehlt.

### Code-Einbindung mit Hilfe von `require()`

Die Funktion `require()` bindet im Prinzip genauso wie `do()` Programmcode aus einer externen Datei ein, allerdings mit dem Unterschied, daß das Einlesen nur einmal geschieht und Perl beim nächsten Aufruf schon "weiß", daß sich der entsprechende Code schon im Speicher befindet und nicht wieder neu geladen werden muß.

Datei `prog.pl`:

    #!/usr/local/bin/perl -w

    print "Erste Zeile des Hauptprogramms\n";
    require "funkt.pl";
    print "Ende des Hauptprogramms\n";

Datei `funkt.pl`:

    print "Ausgabe aus 'funkt.pl'\n";

    Erste Zeile des Hauptprogramms
    Ausgabe aus 'funkt.pl'
    Ende des Hauptprogramms

Ebenso wie `do()` durchsucht auch require() alle Verzeichnispfade in `@INC`.

Ein wesentlicher Unterschied zu `do()` besteht aber darin, daß der Code in der eingebundenen Datei bei der Ausführung eine "wahren" Wert (true) zurückliefern muß. Im obigen Beispiel ist dies relativ offensichtlich, da der Aufruf "`print ...`" eine wahren Wert ("1") zurückgibt (auch wenn er meist nie verwendet wird). Um sicherzugehen, daß externer Code wirklich zum Schluß true liefert, hat es sich eingebürgert, ans Ende der Datei eine kurze Zeile mit dem Inhalt "`1;`" anzuhängen - sie bewirkt die Auswertung von "1", was true entspricht und ist der letzte Aufruf der Datei und somit der Rückgabewert an `require()`.

Die Datei `funkt.pl` aus obigem Beispiel sollte also besser so aussehen:

    print "Ausgabe aus 'funkt.pl'\n";

    1;

Eine zweite Besonderheit von `require()`, die bei der Verwendung von sogenannten Modulen ausgenutzt wird, ist die Tatsache, daß falls als Argument ein Name angegeben wird, der nicht einen in Anführungsstrichen stehenden String darstellt, an diesen Namen automatisch die Endung .pm hinzugefügt wird. Somit sind die Aufrufe im folgenden Beispiel völlig äquivalent:

    #!/usr/local/bin/perl -w

    $dateiname = "extern.pm";
    require $dateiname;
    require 'extern.pm';
    require extern;        # Automatische Ergänzung von .pm

Während die Dateiendung .pl üblicherweise für Skripten/Programme genutzt wird, verwendet man .pm für Dateien, die Perl-Module enthalten.

### Verwendung von `use()`

Noch leistungsfähiger als `require()` ist die Funktion `use()`. Von der Funktion her entspricht ein `use`-Aufruf dem einen von `require` gefolgt von `import`. Letztere ist keine von Perl vordefinierte Funktion sondern eine Funktion, die in einem einzubindenden Modul definiert wird und üblicherweise dazu verwendet wird, um Funktionsnamen zu importieren, damit sie dann genauso wie andere Funktionen im Hauptprogramm aufgerufen werden können.

Ein zweiter Unterschied besteht darin, daß `use()` nicht (wie `require()`) an der entsprechenden Stelle zur Laufzeit des Hauptprogramms abgearbeitet wird, sondern schon bei der Kompilierung des Programms.

Datei `prog.pl`:

    #!/usr/local/bin/perl -w

    print "Erste Zeile des Hauptprogramms\n";
    use modul;     # eigentlich "modul.pm"
    print "Ende des Hauptprogramms\n";

Datei `modul.pm`:

    print "Ausgabe aus 'modul.pm'\n";

    1;

    Ausgabe aus 'modul.pm'
    Erste Zeile des Hauptprogramms
    Ende des Hauptprogramms

An der Reihenfolge der Ausgabe erkennt man schon, daß der Code der Datei modul.pm schon abgearbeitet wird, bevor das eigentliche Hauptprogramm beginnt.

Eine wichtige Konsequenz davon ist, daß man nun nicht mehr durch eine Zeile wie

> `push(@INC,$verzeichnispfad);`

vor dem `use`-Aufruf im Hautprogramm einen zusätzlichen Suchpfad angeben kann, da `use()` schon abgearbeitet wird, bevor überhaupt eine Zeile des Hauptprogramms zur Ausführung kommt. Zur Lösung dieses Problems kann man den entsprechenden `push`-Befehl in einen `BEGIN { ... }`-Block einbetten, so daß auch diese Funktion zur Kompilierungszeit aufgerufen wird.

Datei `prog.pl`:

    #!/usr/local/bin/perl -w

    BEGIN {
      $pfad = 'subdir';
      push(@INC,$pfad);
    }
    print "Erste Zeile des Hauptprogramms\n";
    use modul;
    print "Ende des Hauptprogramms\n";

Datei `modul.pm` im Unterverzeichnis `subdir` :

    print "Ausgabe aus 'modul.pm'\n";

    1;

Autor: Eike Grote | Letzte Änderung: 03.11.2004