\documentclass[dvips]{article}

\usepackage[german]{babel}
\usepackage{graphicx}

\pagestyle{plain}

\title{Perl XS - Tutorial}
\author{Steven Schubiger}

\begin{document}

\maketitle

\begin{center}

\begin{abstract}

Dieses Tutorial wird den geneigten Leser in den Schritten unterweisen,
die n\"otig sind, um eine eigene compilierte Perl Erweiterung zu erstellen.
\newline\newline
Das Tutorial beginnt mit sehr simplen Beispielen und wird mit jedem Beispiel,
welches neue Optionen zum Repertoire hinzuf\"ugt, komplexer. Gewisse Konzepte
m\"ogen nicht ausreichend erl\"autert sein bis zu einem sp\"ateren Zeitpunkt mit
der Absicht den Leser sachte in die Thematik einzuweihen.
\newline\newline
Dieses Tutorial wurde mit dem Fokus auf Unix geschrieben. Sofern es gewisse
Unterschiede zwischen Plattformen geben sollte, werden jene aufgelistet.
Sollte eine Abweichung nicht dokumentiert sein, bittet der Autor um eine
Benachrichtigung.

\end{abstract}

\end{center}

\pagebreak
\tableofcontents

\section{Notizen am Rande}

\subsection{make}

Diese Einf\"uhrung nimmt an, dass das make Programm, welches Perl verwendet,
\verb+make+ lautet. Anstatt make in den Beispielen, die folgen werden, zu verwenden,
m\"oge man das make spezifizieren, welches Perl gem\"ass Konfiguration
verwendet. Jene Information ist durch \textbf{perl -V:make} in Erfahrung
zu bringen.

\subsection{Versionen}

Wenn man eine Perl Erweiterung f\"ur den generellen Gebrauch verfasst,
ist zu erwarten, dass sie mit Perl Versionen verwendet wird, die von der eigenen
Version abweichen. Da du dieses Dokument liest, ist es wahrscheinlich, dass deine
Versionnummer von Perl 5.005 oder neuer ist; deine User m\"ogen jedoch
vielleicht \"altere Versionen haben.
\newline\newline
Um zu verstehen was f\"ur Inkompatiblit\"aten man erwarten k\"onnte, und in
dem seltenen Falle, dass deine Perl Version \"alter wie dieses Dokument
ist, siehe die Sektion ``Fehlerbehebung in den Beispielen''.
\newline\newline
Sofern deine Erweiterung gewisse Optionen von Perl gebraucht, welche in \"alteren
Versionen nicht verf\"ugbar sind, w\"urden deine Benutzer eine fr\"uhe sinnvolle
Warnung begr\"ussen. Du solltest jene wahrscheinlich in die \emph{README} Datei packen,
aber heutzutage werden Erweiterungen z.T. automatisch installiert, gef\"uhrt durch
das \emph{CPAN.pm} Modul oder anderen Modulen.
\newline\newline
In MakeMaker-basierenden Installationen, stellt das \emph{Makefile.PL} die fr\"uheste
M\"oglichkeit dar, um Versionspr\"ufungen durchzuf\"uhren. Man kann zB. f\"ur jenen
Zweck das \emph{Makefile.PL} so aussehen lassen:

\begin{verbatim}
eval { require 5.007 }
    or die <<EOD;
############
### Dieses Modul gebraucht das frobnication Framework,
### welches nicht verfuegbar ist vor der Perl Version
### 5.007. Erneuern Sie ihr Perl bevor Sie Kara::Mba
### installieren.
############
EOD
\end{verbatim}

\subsection{Dynamisches laden versus statisches laden}

Es ist eine von vielen geteilte Ansicht, dass wenn man nicht die M\"oglichkeit hat
dynamisch eine Bibliothek zu laden, man keine XSUBs compilieren kann. Dies ist nicht wahr.
Man \emph{kann} sie compilieren, aber man muss die XSUBs Routinen mit dem restlichen Perl
linken, um somit eine ausf\"uhrbare Datei zu erzeugen. \"Ahnlich ist es in Perl 4.
\newline\newline
Selbst auf solch einem System kann diese Einf\"uhrung nutzbringend verwendet werden.
Der XSUB Erzeugungsmechanismus wird das System \"uberpr\"ufen und nach M\"oglichkeit
eine dynamisch-ladbare Bibliothek erzeugen; wenn nicht m\"oglich, wird eine statische
Bibliothek ins Leben gerufen und eine zugeh\"orige, ausf\"uhrbare Datei mit jener
Bibliothek gelinkt.
\newline\newline
Sollte es erw\"unscht sein eine statisch-gelinkte, ausf\"uhrbare Datei auf einem
System zu erzeugen, welches dynamisches-laden erlaubt, m\"oge man in den folgenden
Beispielen, wo \verb+make+ ohne Argumente ausgef\"uhrt wird, stattdessen den Befehl
\verb+make perl+ ausf\"uhren.
\section{Einf\"uhrung}
\subsection{Beispiel 1}
Unsere erste Erweiterung wird \"uberaus einfach sein. Wenn wir die Routine in der
Erweiterung aufrufen, wird sie eine wohlbekannte Nachricht ausgeben und zur\"uckkehren.
\newline\newline
F\"uhre \verb+h2xs -A -n Mytest+ aus. Dies wird ein Verzeichnis namens Mytest erstellen,
m\"oglicherweise unter ext/ wenn jenes Verzeichnis im aktuellen existiert. Mehrere Dateien
werden im Mytest Verzeichnis erzeugt, u.a. MANIFEST, Makefile.PL, Mytest.pm, Mytest.xs,
test.pl und Changes.
\newline\newline
Die MANIFEST Datei enth\"alt die Namen aller Dateien, die soeben im Mytest Verzeichnis
erzeugt wurden.
\newline\newline
Die Datei Makefile.PL sollte in etwa so aussehen:

\begin{verbatim}
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
    NAME         => 'Mytest',
    VERSION_FROM => 'Mytest.pm', # finds $VERSION
    LIBS         => [''],   # e.g., '-lm'
    DEFINE       => '',     # e.g., '-DHAVE_SOMETHING'
    INC          => '',     # e.g., '-I/usr/include/other'
);
\end{verbatim}

Die Datei Mytest.pm sollte in etwa so starten:

\begin{verbatim}
package Mytest;

use strict;
use warnings;

require Exporter;
require DynaLoader;

our @ISA = qw(Exporter DynaLoader);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
our @EXPORT = qw(

);
our $VERSION = '0.01';

bootstrap Mytest $VERSION;

# Preloaded methods go here.

# Autoload methods go after __END__, and are processed by the autosplit program.

1;
__END__
# Below is the stub of documentation for your module. You better edit it!
\end{verbatim}

Der Rest der .pm Datei enth\"alt Beispielcode um Dokumentation zur Verf\"ugung zu stellen.
\newline\newline
Die Mytest.xs Datei sollte schlussendlich etwa so aussehen:

\begin{verbatim}
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

MODULE = Mytest    PACKAGE = Mytest
\end{verbatim}

Man m\"oge die .xs Datei editieren, um jenes am Ende hinzuzuf\"ugen:

\begin{verbatim}
void
hello()
    CODE:
        printf("Hello, world!\n");
\end{verbatim}

Es ist annehmbar das die Zeilen beginnend bei CODE: nicht einger\"uckt werden.
Wie dem auch sei, die Lesbarkeit betreffend, wird es empfohlen, dass man CODE:
eine Stufe einr\"uckt und die nachfolgenden Zeilen noch eine.
\newline\newline
F\"uhre nun \verb+perl Makefile.PL+ aus. Dies wird ein reelles Makefile erzeugen,
welches make ben\"otigt. Die Ausgabe ist in etwa so:

\begin{verbatim}
 % perl Makefile.PL
 Checking if your kit is complete...
 Looks good
 Writing Makefile for Mytest
 %
\end{verbatim}

Nun, make ausf\"uhrend wird in etwa solch eine Ausgabe produzieren (gewisse Zeilen
wurden der Leserlichkeit halber gek\"urzt und gewisse andere wurden entfernt):

\begin{verbatim}
% make
umask 0 && cp Mytest.pm ./blib/Mytest.pm
perl xsubpp -typemap typemap Mytest.xs >Mytest.tc && mv Mytest.tc Mytest.c
Please specify prototyping behavior for Mytest.xs (see perlxs manual)
cc -c Mytest.c
Running Mkbootstrap for Mytest ()
chmod 644 Mytest.bs
LD_RUN_PATH="" ld -o ./blib/PA-RISC1.1/auto/Mytest/Mytest.sl -b Mytest.o
chmod 755 ./blib/PA-RISC1.1/auto/Mytest/Mytest.sl
cp Mytest.bs ./blib/PA-RISC1.1/auto/Mytest/Mytest.bs
chmod 644 ./blib/PA-RISC1.1/auto/Mytest/Mytest.bs
Manifying ./blib/man3/Mytest.3
%
\end{verbatim}

Man kann die Zeile \"uber 'prototyping behavior' ohne weitere Bedenken ignorieren.
\newline\newline
Wenn du \"uber ein Win32 System verf\"ugst und der Compilierprozess scheitert mit Linker
Fehlermeldungen f\"ur Funktionen in der C Bibliothek, \"uberpr\"ufe ob dein Perl
konfiguriert wurde, um PerlCRT zu gebrauchen (\textbf{perl -V:libc} ausf\"uhrend sollte jenes
anzeigen, sofern es der Fall sein sollte). Wenn dein Perl konfiguriert wurde um PerlCRT
zu gebrauchen, vergewissere dich, ob die PerlCRT.lib an der selbigen Stelle wie
msvcrt.lib vorhanden ist, sodass der Compiler jene selber orten kann. Die msvcrt.lib
wird gew\"ohnlicherweise in dem lib Verzeichnis von dem Visual C Compiler gefunden
(d.h. C:/DevStudio/VC/lib).
\newline\newline
Perl verf\"ugt \"uber eine spezielle M\"oglichkeit einfach Test Scripts zu verfassen,
aber nur f\"ur dieses Beispiel werden wir unser eigenes Test Script erzeugen.
Kreiere eine Datei namens hello, welche wie folgt aussieht:

\begin{verbatim}
#! /opt/perl5/bin/perl

use ExtUtils::testlib;

use Mytest;

Mytest::hello();
\end{verbatim}

Nun setzen wir die Dateirechte des Scripts auf ausf\"uhrbar (\verb%chmod +x hello%), f\"uhren es aus und sehen
folgende Ausgabe:

\begin{verbatim}
% ./hello
Hello, world!
%
\end{verbatim}

\subsection{Beispiel 2}

Nun werden wir unserer Erweiterung eine Subroutine hinzuf\"ugen, welche ein einzelnes
numerisches Argument als Eingabe entgegenimmt und wenn die Nummer durch zwei teilbar ist,
0 retourniert, ansonsten 1.
\newline\newline
F\"uge folgendes am Ende von Mytest.xs an:

\begin{verbatim}
int
is_even(input)
            int input
        CODE:
            RETVAL = (input % 2 == 0);
        OUTPUT:
            RETVAL
\end{verbatim}

Es braucht kein Leerzeichen am Anfang der Zeile \verb+'int input'+ zu sein, es erh\"oht jedoch die
Lesbarkeit. Ob ein Semikolon am Ende jener Zeile verwendet wird ist optional. Eine
variable Anzahl an Leerzeichen kann zwischen \verb+int+ und \verb+input+ eingef\"ugt werden.
\newline\newline
F\"uhre nochmals make aus, um die neue geteilte Bibliothek zu compilieren.
\newline\newline
Nun f\"uhre nochmals die gleichen Schritte aus wie zuvor, ein Makefile von der Makefile.PL
Datei erzeugend und make ausf\"uhrend.
\newline\newline
Um so sehen, ob unsere Erweiterung funktioniert, m\"ussen wir die Datei test.pl begutachten.
Diese Datei ist so strukturiert, dass sie dieselben Test Strukturen, welche Perl hat, imitiert.
Innerhalb des Test Scripts, werden eine Anzahl an Tests ausgef\"uhrt, um die Funktionalit\"at
zu best\"atigen. 'ok' ausgebend wenn der Test korrekt ist, 'not' wenn nicht. \"Andere die
print Anweisung in dem BEGIN Block, sodass sie 1..4 ausgibt und f\"uge folgenden Code
am Ende hinzu:

\begin{verbatim}

print &Mytest::is_even(0) == 1 ? "ok 2" : "not ok 2", "\n";
print &Mytest::is_even(1) == 0 ? "ok 3" : "not ok 3", "\n";
print &Mytest::is_even(2) == 1 ? "ok 4" : "not ok 4", "\n";
\end{verbatim}

Wir werden jenes Test Script durch den Befehl \verb+make test+ ausf\"uhren. Du solltest in etwa
folgende Ausgabe sehen:

\begin{verbatim}
% make test
PERL_DL_NONLAZY=1 /opt/perl5.004/bin/perl (lots of -I arguments) test.pl
1..4
ok 1
ok 2
ok 3
ok 4
%
\end{verbatim}

\subsection{Was geschah?}

Das Programm h2xs ist der Ausgangspunkt, um Erweiterungen zu kreieren. In sp\"ateren Beispielen
werden wir sehen, wie man h2xs gebrauchen kann, um Header Dateien zu lesen und Vorlagen zu
erzeugen, um C Routinen aufzurufen.
\newline\newline
h2xs erzeugt eine Anzahl an Dateien im Erweiterungs Verzeichnis. Die Datei Makefile.PL ist ein
Perl Script, welches ein echtes Makefile generiert um die Erweiterung zu 'compilieren'. Wir werden
sp\"ater einen genaueren Blick drauf werfen.
\newline\newline
Die .pm und .xs Dateien sind die Grundlage der Erweiterung. Die .xs Datei beinhaltet die C
Routinen, welche die Erweiterung ausmachen. Die .pm Datei enth\"alt Routinen, die Perl das laden
der Erweiterung erm\"oglicht.
\newline\newline
Die Generierung des Makefile (\verb+make+ ausf\"uhrend) kreierte ein Verzeichnis namens blib (Synonym
f\"ur build library) in dem aktuellen Verzeichnis. Dieses Verzeichnis beinhaltet die geteilte
Bibliothek, welche wir 'compilieren' werden. Wenn wir sie getestet haben, k\"onnen wir sie an der finalen
Stelle installieren.
\newline\newline
Das Test Script via \verb+make test+ ausf\"uhrend tat etwas sehr wichtiges. Es rufte Perl mit all jenen
-I Argumenten auf, sodass es die verschiedenen Dateien finden konnte, die Teil der Erweiterung sind.
Es ist sehr wichtig, dass wenn du Erweiterungen testest, \verb+make test+ verwendest. Wenn du versuchst
das Test Script nur f\"ur sich selbst auzurufen, wirst du einen fatal error erzeugen. Ein anderer
wichtiger Grund um \verb+make test+ zu gebrauchen, ist wenn du ein Upgrade einer bestehenden Erweiterung
testest, wird \verb+make test+ die neue Version der Erweiterung gebrauchen.
\newline\newline
Wenn Perl eine \verb+use extension;+ sieht, sucht es nach einer Datei mit demselben Namen wie der \verb+used+
extension mit einem .pm Suffix. Wenn jene Datei nicht gefunden werden kann, gibt Perl einen fatal error aus.
Der Standard Suchpfad ist im \verb+@INC+ Array enthalten.
\newline\newline
In unserem Falle, teilt Mytest.pm Perl mit, dass es die Exporter und Dynamic Loader Erweiterungen ben\"otigt.
Nachfolgend setzt es das \verb+@ISA+ und \verb+@EXPORT+ Array und den \verb+$VERSION+ String; abschliessend
teilt es Perl mit, dass es das Modul laden (bootstrapen) soll.
\newline\newline
Die beiden Arrays \verb+@ISA+ und \verb+@EXPORT+ sind sehr wichtig. Das \verb+@ISA+ Array enth\"alt eine Liste
anderer Pakete in welchen man nach Methoden zu suchen hat, die im aktuellen Paket nicht existieren. Dies ist
in der Regel nur von Bedeutung f\"ur objekt-orientierte Erweiterungen; normalerweise muss es nicht modifiziert
werden.
\newline\newline
Das \verb+@EXPORT+ Array teilt Perl mit welche der Variablen und Subroutinen der Erweiterung im Namensraum des
rufenden Pakets platziert werden sollen. Da wir nicht wissen, ob der Benutzer bereits unsere Variabeln
und Subroutinen Namen verwendet, ist es wesentlich sorgf\"altig zu selektieren, was exportiert werden
soll. Exportiere nicht Methoden oder Variabeln automatisch ohne einen guten Grund.
\newline\newline
Als eine Faustregel, wenn das Modul objekt-orientiert zu sein versucht, exportiere nichts.
Wenn es nur eine Sammlung an Funktionen und Variabeln ist, kannst du via einem anderen Array, dem sog.
@EXPORT\_OK exportieren. Dieses Array platziert nicht automatisch Subroutinen und Variabelnamen im
Namensraum ausser der Benutzer fordert es explizit so an.
\newline\newline
Die \verb+$VERSION+ Variable wird gebraucht um sicherzustellen, dass die .pm Datei und die geteilte Bibliothek
'in sync' sind. Nach jeder \"Anderung, sollte man den Wert jener Variable inkrementieren.
\subsection{Gute Tests schreiben}
Die Wichtigkeit gute Test Scripts zu schreiben kann nicht \"uberm\"assig betont werden. Man sollte nah am
Geschehen dem 'ok/not ok' Stil folgen, welcher Perl gebraucht, sodass es sehr einfach und nicht zweideutig
ist das Resultat sinngem\"ass zu interpretieren. Sofern du einen Fehler findest und jenen behebst, schreibe
einen Test daf\"ur.
\newline\newline
Durch Ausf\"uhrung von \verb+make test+, stellst du sicher, dass dein test.pl l\"auft und das es die korrekte Version
deiner Erweiterung gebraucht. Wenn du viele Testf\"alle haben solltest, ziehe in Betracht Perl's Test Stil zu
verwenden. Erstelle ein Verzeichnis namens t im Erweiterungs Verzeichnis und f\"ugen das Suffix .t den Namen
deiner Dateien an. Wenn du \verb+make test+ eingibst, werden all jene Dateien ausgef\"uhrt.

\subsection{Beispiel 3}

Unsere dritte Erweiterung wird ein Argument als Eingabe nehmen, jenes runden und den gerundeten Wert dem \emph{Argument}
zuweisen.
\newline\newline
F\"uge folgendes dem Ende von Mytest.xs an:

\begin{verbatim}
void
round(arg)
            double  arg
        CODE:
            if (arg > 0.0) {
                arg = floor(arg + 0.5);
            } else if (arg < 0.0) {
                arg = ceil(arg - 0.5);
            } else {
                arg = 0.0;
            }
        OUTPUT:
            arg
\end{verbatim}

Editiere das Makefile.PL, sodass die korrespondierende Zeile wie folgt aussieht:

\begin{verbatim}
'LIBS'      => ['-lm'],   # e.g., '-lm'
\end{verbatim}

Generiere das Makefile und f\"uhre make aus. \"Andere den BEGIN Block, sodass
er 1..9 ausgibt und f\"uge folgendes dem test.pl hinzu:

\begin{verbatim}
$i = -1.5; &Mytest::round($i); print $i == -2.0 ? "ok 5" : "not ok 5", "\n";
$i = -1.1; &Mytest::round($i); print $i == -1.0 ? "ok 6" : "not ok 6", "\n";
$i = 0.0; &Mytest::round($i); print $i == 0.0 ? "ok 7" : "not ok 7", "\n";
$i = 0.5; &Mytest::round($i); print $i == 1.0 ? "ok 8" : "not ok 8", "\n";
$i = 1.2; &Mytest::round($i); print $i == 1.0 ? "ok 9" : "not ok 9", "\n";
\end{verbatim}

\verb+make test+ ausf\"uhrend sollte f\"ur alle neun Tests ok ausgeben.
\newline\newline
Nehme zur Kenntnis, dass in diesen neuen Testf\"allen eine skalare Variable
\"ubergeben wurde. Du wirst dich vielleicht wundern, ob man eine Konstante oder
Literale runden kann. Um zu sehen, was passiert, f\"uge tempor\"ar folgende
Zeile test.pl hinzu:

\begin{verbatim}
&Mytest::round(3);
\end{verbatim}

F\"uhre \verb+make test+ aus und stelle fest, dass Perl einen fatal error ausgibt.
Perl l\"asst dich nicht den Wert einer Konstante \"andern!

\subsection{Was ist hier neu?}

\begin{itemize}

\item Wir \"anderten das Makefile.PL. In diesem Falle, spezifizierten wir eine zus\"atzliche
Bibliothek, die in die geteilte Bibliothek von der Erweiterung gelinkt wurde, namentlich die
Mathematik Bibliothek libm. Wir werden sp\"ater sehen wie man XSUBs verfasst, die jede
Routine in einer Bibliothek aufrufen k\"onnen.

\item Das Argument, welches an die Funktion \"ubergeben wurde, wird nicht zur\"uckgeliefert
als R\"uckgabewert; vielmehr wird es der Variable, die \"ubergeben wurde, zugewiesen.
Du wirst es vielleicht erraten haben als du gesehen hast, das der R\"uckgabewert vom Typ 'void' war.

\end{itemize}

\subsection{Ein-/Ausgabe Parameter}
Du spezifizierst, welche Parameter an die XSUB \"ubergeben werden auf der Zeile, die nach
der Definition der Funktion's R\"uckgabewert und Name folgt. Jede Eingabe Parameter Zeile
beginnt mit einem optionalen Leerzeichen und kann ein ebenso optionales terminierendes
Semikolon enthalten.
\newline\newline
Die Liste der Ausgabe Parameter befindet sich am Ende der Funktion, gerade vor der OUTPUT:
Direktive. Die Verwendung von RETVAL teilt Perl mit, dass es erw\"unscht ist, dass jener
Wert zur\"uckgeliefert wird als R\"uckgabewert der XSUB Funktion. In Beispiel 3, war es
erw\"unscht, dass der R\"uckgabewert in der originalen Variable platziert wurde; deshalb
wurde sie in der OUTPUT: Sektion aufgef\"uhrt.

\subsection{Das XSUBPP Programm}

Das \textbf{xsubpp} Programm liest den XS Code in der .xs Datei und \"ubersetzt es in C Code,
ausgegeben in eine Datei deren Suffix .c ist. Der generierte C Code verwendet \"uberm\"assig
stark die C Funktionen innerhalb Perl.

\subsection{Die TYPEMAP Datei}

Das \textbf{xsubpp} Programm verwendet Regeln um von Perl's Datentypen (String, Array, etc.) zu C's Datentypen
(int, char, etc.) zu konvertieren. Jene Regeln werden in der typemap Datei aufbewahrt (\$PERLLIB/ExtUtils/typemap).
Diese Datei wird in drei Teile unterteilt.
\newline\newline
Die erste Sektion weist verschiedenen C Datentypen einem Namen zu, der mit den Perl Datentypen korrespondiert.
Die zweite Sektion beinhaltet C Code, welcher \textbf{xsubpp} gebraucht, um Eingabe Parameter zu verarbeiten.
Die dritte Sektion beinhaltet C Code, welcher \textbf{xsubpp} gebraucht, um Ausgabe Parameter zu verarbeiten.
\newline\newline
M\"ogen wir einen Blick auf den Teil der .c Datei werfen, die f\"ur unsere Erweiterung kreiert wurde. Der Dateiname ist Mytest.c:

\begin{verbatim}
XS(XS_Mytest_round)
{
    dXSARGS;
    if (items != 1)
        croak("Usage: Mytest::round(arg)");
    {
        double  arg = (double)SvNV(ST(0));/* XXXXX */
        if (arg > 0.0) {
            arg = floor(arg + 0.5);
        } else if (arg < 0.0) {
            arg = ceil(arg - 0.5);
        } else {
            arg = 0.0;
        }
        sv_setnv(ST(0), (double)arg);/* XXXXX */
    }
    XSRETURN(1);
}
\end{verbatim}

Man nehme die beiden Zeilen kommentiert mit 'XXXXX' zur Kenntnis. Wenn du die erste Sektion der
typemap Datei pr\"ufst, wirst du sehen, das doubles vom Typ T\_DOUBLE sind. In der INPUT Sektion
wird ein Argument, welches vom Typ T\_DOUBLE ist, der Variable arg zugewiesen indem die Routine
SvNV oder \"ahnlich aufgerufen, dann zu double gecastet und schlussendlich der Variable arg
zugewiesen wird. \"Ahnliches geschieht in der OUTPUT Sektion; sobald arg seinen finalen Wert hat,
wird es der sv\_setnv Funktion \"ubergeben, um es an die aufzurufende Subroutine zur\"uckzugeben.

\subsection{Warnungen betr. Ausgabe Argumenten}

Generell gesprochen, ist es keine gute Idee Erweiterungen zu schreiben, welche die Eingabe Parameter
\"andern, wie in Beispiel 3. Stattdessen, sollte man wahrscheinlich multiple Werte in einem Array 
retournieren und den Caller jene verarbeiten lassen. Wie auch immer, um uns besser an existierende
C Routinen anzupassen, welche oftmals ihre Eingabe Parameter \"andern, wird jenes Verhalten toleriert.

\subsection{Beispiel 4}

In diesem Beispiel werden wir beginnen XSUBs zu schreiben, welche mit vordefinierten C Bibliotheken
interagieren werden. Zu Beginn weg werden wir selber eine kleine Bibliothek schreiben, dann lassen
wir h2xs unsere .pm und .xs Dateien erzeugen.
\newline\newline
Erstelle ein neues Verzeichnis namens Mytest2 auf der selben Stufe wie das Verzeichnis Mytest.
Im Mytest2 Verzeichnis erzeugst du ein Verzeichnis namens mylib und wechselst dann in jenes.
\newline\newline
Nun kreieren wir einige Dateien, welche eine Test Bibliothek generieren werden. Jene werden eine
C Quelldatei inkludieren und eine Headerdatei. Wir werden auch ein Makefile.PL in diesem Verzeichnis
erzeugen. Anschliessend stellen wir sicher, dass wenn make in der Mytest2 Stufe ausgef\"uhrt wird
automatisch die Makefile.PL Datei ausf\"uhrt und das resultierende Makefile.
\newline\newline
Erzeuge im mylib Verzeichnis eine Datei namens mylib.h, welche wie folgt aussieht:

\begin{verbatim}
#define TESTVAL 4

extern double   foo(int, long, const char*);
\end{verbatim}

Erzeuge auch eine Datei namens mylib.c, die wie folgt aussieht:

\begin{verbatim}
#include <stdlib.h>
#include "./mylib.h"

double
foo(int a, long b, const char *c)
{
    return (a + b + atof(c) + TESTVAL);
}
\end{verbatim}

Und schlussendlich, erzeuge eine Datei namens Makefile.PL, die wie folgt aussieht:

\begin{verbatim}
use ExtUtils::MakeMaker;
$Verbose = 1;
WriteMakefile(
    NAME   => 'Mytest2::mylib',
    SKIP   => [qw(all static static_lib dynamic dynamic_lib)],
    clean  => {'FILES' => 'libmylib$(LIB_EXT)'},
);

sub MY::top_targets {
    '
    all :: static

    pure_all :: static

    static ::       libmylib$(LIB_EXT)

    libmylib$(LIB_EXT): $(O_FILES)
        $(AR) cr libmylib$(LIB_EXT) $(O_FILES)
        $(RANLIB) libmylib$(LIB_EXT)

    ';
}
\end{verbatim}

Vergewissere dich, dass du Tabulatoren und keine Leerzeichen in den
Zeilen mit \$(AR) und \$(RANLIB) beginnend verwendest. Make funktioniert nicht
richtig, wenn du Leerzeichen verwenden solltest. Es wurde auch berichtet, dass das cr
Argument f\"ur \$(AR) auf Win32 Systemen unn\"otig ist.
\newline\newline
Wir werden nun die Hauptdateien der obersten Stufe erstellen. Wechsele ins
Verzeichnis \"uber Mytest2 und f\"uhre folgenden Befehl aus:

\begin{verbatim}
% h2xs -O -n Mytest2 ./Mytest2/mylib/mylib.h
\end{verbatim}

Dies wird eine Warnung bez\"uglich dem \"uberschreiben von Mytest2 ausgeben,
aber dies ist akzeptabel. Unsere Dateien befinden sich in Mytest2/mylib und
bleiben unver\"andert.
\newline\newline
Das \"ubliche Makefile.PL, welches h2xs generiert, weiss nichts von dem mylib
Verzeichnis. Es ist vonn\"oten anzugeben das ein Unterverzeichnis existiert
und dass wir darin eine Bibliothek erzeugen werden. F\"uge das Argument
MYEXTLIB dem WriteMakefile Aufruf hinzu, sodass es folgendermassen aussieht:

\begin{verbatim}
WriteMakefile(
    'NAME'      => 'Mytest2',
    'VERSION_FROM' => 'Mytest2.pm', # finds $VERSION
    'LIBS'      => [''],   # e.g., '-lm'
    'DEFINE'    => '',     # e.g., '-DHAVE_SOMETHING'
    'INC'       => '',     # e.g., '-I/usr/include/other'
    'MYEXTLIB' => 'mylib/libmylib$(LIB_EXT)',
);
\end{verbatim}

F\"uge nun am Ende ein Subroutine hinzu (welche die vorherige \"uberschreibt).
Nehme zur Kenntnis, dass ein Tabulator f\"ur die Einr\"uckung der Zeile mit cd
beginnend vonn\"oten ist.

\begin{verbatim}
sub MY::postamble {
'
    $(MYEXTLIB): mylib/Makefile
                    cd mylib && $(MAKE) $(PASSTHRU)
    ';
}
\end{verbatim}

\"Andere auch die MANIFEST Datei, sodass sie akkurat den Inhalt
deiner Erweiterung widerspiegelt. Die einzelne Zeile, welche ``mylib''
enth\"alt sollte durch folgende drei Zeilen ersetzt werden:

\begin{verbatim}
mylib/Makefile.PL
mylib/mylib.c
mylib/mylib.h
\end{verbatim}

Um unseren Namensraum rein und unverschmutzt zu halten, editiere
die .pm Datei und \"andere die Variable \verb+@EXPORT+ zu \verb+@EXPORT_OK+. Abschliessend
editiere die .xs Datei, sodass die include Zeile folgendermassen ausschaut:

\begin{verbatim}
#include "mylib/mylib.h"
\end{verbatim}

F\"uge auch folgende Funktionsdefinition der .xs Datei am Ende an:

\begin{verbatim}
double
foo(a,b,c)
        int             a
        long            b
        const char *    c
   OUTPUT:
        RETVAL
\end{verbatim}

Nun m\"ussen wir auch eine typemap Datei erzeugen, da das Standard Perl momentan
den const char * Typ nicht unterst\"utzt. Erstelle eine Datei namens typemap
im Mytest2 Verzeichnis und f\"uge folgendes ein:

\begin{verbatim}
const char *    T_PV
\end{verbatim}

F\"uhre nun das Makefile.PL im obersten Verzeichnis aus. Nehme zur
Kenntnis, dass es auch ein Makefile im mylib Verzeichnis erstellt hat. F\"uhre
make aus und beobachte, dass es ins mylib Verzeichnis wechselt, um dort
make auch auszuf\"uhren.
\newline\newline
Editiere nun das test.pl Script und \"andere den BEGIN Block, sodass er
1..4 ausgibt; desweiteren f\"uge folgende Zeilen dem Ende des Scripts an:

\begin{verbatim}
print &Mytest2::foo(1, 2, "Hello, world!") == 7 ? "ok 2\n" : "not ok 2\n";
print &Mytest2::foo(1, 2, "0.0") == 7 ? "ok 3\n" : "not ok 3\n";
print abs(&Mytest2::foo(0, 0, "-3.4") - 0.6) <= 0.01 ? "ok 4\n" : "not ok 4\n";
\end{verbatim}

Wenn man mit Fliesskommazahl Vergleichen zu tun hat, ist es am besten nicht auf
Gleichheit zu pr\"ufen, sondern viel eher ob die Differenz zwischen dem erwarteten und
dem eigentlichen Resultat unter einer gewissen Schwelle liegt, die in diesem Falle 0.01
ist.
\newline\newline
F\"uhre \verb+make test+ aus und alles sollte in Ordnung sein.

\subsection{Was geschah hier?}

Nicht wie in vorherigen Beispielen haben wir h2xs an einer realen Include Datei getestet.
Dies verursachte, dass einiges positives sowohl in der .pm wie auch .xs Datei gefunden werden
kann.

\begin{itemize}

\item In der .xs Datei ist nun eine include Direktive mit dem absoluten Pfad zur mylib.h Header
Datei. Wir haben jenen Pfad in einen relativen ge\"andert, sodass wir des Erweiterungs Verzeichnis
umbennen k\"onnten, sofern wir dies m\"ochten.

\item Es wurde einiger neuer C Code der .xs Datei hinzugef\"ugt. Der Zweck der \verb+constant+ Routine ist es
die Werte welche in der Header Datei definiert sind dem Perl Script zug\"anglich zu machen (entweder
durch aufrufen von \verb+TESTCAL+ oder \verb+\&Mytest2::TESTVAL+). Es gibt auch XS Code um Aufrufe an die
\verb+constant+ Routine zuzulassen.

\item Die .pm Datei exportierte urspr\"unglich das Symbol \verb+TESTVAL+ im \verb+@EXPORT+ Array. Dies k\"onnte
Namenskollisionen hervorrufen. Eine gute Faustregel ist es, dass wenn define nur von C Routinen verwendet
wird und nicht vom Benutzer selbst, es aus dem \verb+@EXPORT+ Array entfernt werden sollte. Nebst dem, wenn
es dich nicht weiter st\"oren sollte den vollst\"andig qualifizierten Namen einer Variable zu gebrauchen,
kannst du die meisten Elemente aus dem \verb+@EXPORT+ Array nach \verb+@EXPORT_OK+ z\"ugeln.

\item H\"atte unsere Header Datei include Direktiven erhalten, w\"aren sie nicht ordnungsgem\"ass durch h2xs
verarbeitet worden. Es gibt keine wirklich gute L\"osung dbzgl. momentan.

\item Wir haben Perl auch von der Bibliothek, die wir im mylib Unterverzeichnis erstellt haben, mitgeteilt.
Dies ben\"otigte nur das hinzuf\"ugen der \verb+MYEXTLIB+ Variable an den WriteMakefile Aufruf und das ersetzen
der Postamble Subroutine, sodass es ins Unterverzeichnis wechselt und make ausf\"uhrt. Das Makefile.PL
f\"ur die Bibliothek ist ein wenig mehr komplexer, aber nicht exzessiv. Wir haben soeben wieder die Postamble
Subroutine durch unseren eigenen Code ersetzt. Jener Code spezifizierte ganz einfach, dass die Bibliothek,
die erstellt werden sollte eine statische Archiv Bibliothek ist (im Gegensatz zur dynamisch-ladbaren Bibliothek)
und f\"ugte die Befehle, um sie zu compilieren, an.

\end{itemize}

\subsection{Anatomie einer .xs Datei}

Die .xs Datei in Beispiel 4 bestand aus einigen neuen Elementen. Um die Bedeutung jener Elemente zu verstehen,
ist Aufmerksamkeit gegen\"uber folgender Zeile geboten:

\begin{verbatim}
MODULE = Mytest2        PACKAGE = Mytest2
\end{verbatim}

Alles vor dieser Zeile ist C Code, der beschreibt, welche Header Dateien zu inkludieren sind, und einige
Funktionen definiert. Keine \"Ubersetzungen werden hiermit durchgef\"uhrt, nebst dem \"uberspringen von
eingebetteter POD Dokumentation wird alles so wie es ist in die generierte C Ausgabedatei eingef\"ugt.
\newline\newline
Alles nach dieser Zeile beschreibt XSUB Funktionen. Diese Beschreibungen werden \"ubersetzt von \textbf{xsubpp}
in C Code, welcher diese Funktionen - Perl Aufrufkonventionen gebrauchend - implementiert und jene f\"ur
den Perl Interpreter sichtbar macht.
\newline\newline
Schenke der Funktion \verb+constant+ deine Aufmerksamkeit. Jener Name erscheint zweimal in der generierten .xs
Datei: einmal im ersten Teil, als statische C Funktion, dann ein anderes Mal im zweiten Teil, wenn eine XSUB
Schnittstelle zur statischen C Funktion definiert wird.
\newline\newline
Dies ist typisch f\"ur .xs Dateien: normalerweise stellt die .xs Datei eine Schnittstelle zu einer existierenden
C Funktion zur Verf\"ugung. Dann wird jene C Funktion andersweitig definiert (entweder in einer externen
Bibliothek oder im ersten Abschnitt einer .xs Datei) und eine Perl Schnittstelle zu jener Funktion wird im
zweiten Teil der .xs  Datei beschrieben. Die Situation wie sie in Beispiel 1, Beispiel 2 und Beispiel 3 vorkommt,
wenn g\"anzlich alle Arbeit innerhalb der Perl Ebene getan wird, ist viel eher eine Ausnahme als die Regel.

\subsection{XSUBs ausreizen}

In Beispiel 4 enth\"alt der zweite Teil der .xs Datei die folgende Beschreibung einer XSUB:

\begin{verbatim}
double
foo(a,b,c)
        int             a
        long            b
        const char *    c
    OUTPUT:
        RETVAL
\end{verbatim}

Nehme zur Kenntnis das im Gegensatz zu Beispiel 1, Beispiel 2 und Beispiel 3 die Beschreibung
keinerlei aktuellen Code enth\"alt, der beschreibt, was getan werden soll wenn die Perl Funktion foo()
aufgerufen wird. Um Verst\"andnis zu erlangen was hier vorgeht, f\"uge folgende CODE Sektion der
XSUB an:

\begin{verbatim}
double
foo(a,b,c)
        int             a
        long            b
        const char *    c
    CODE:
        RETVAL = foo(a,b,c);
    OUTPUT:
        RETVAL
\end{verbatim}

Wie dem auch sei, diese beiden XSUBs stellen beinahe identisch generierten Code zur Verf\"ugung:
der \textbf{xsubpp} Compiler ist ausreichend intelligent, um die \verb+CODE:+ Sektion von den ersten beiden
Zeilen der Beschreibung einer XSUB auszumachen. Wie siehts bzgl. \verb+OUTPUT:+ Sektion aus? Es ist identisch.
Die \verb+OUTPUT:+ Sektion kann ebenfalls entfernt werden, sofern keine \verb+CODE:+ oder \verb+PPCODE:+ Sektion
spezifiziert wird: \textbf{xsubpp} erkennt, dasses eine Funktionsaufruf Sektion generieren muss und wird die
\verb+OUTPUT:+ Sektion ebenfalls automatisch erstellen. Folgendermassen kann die XSUB auf folgendes reduziert
werden:

\begin{verbatim}
double
foo(a,b,c)
        int             a
        long            b
        const char *    c
\end{verbatim}

L\"asst sich selbiges mit einer XSUB

\begin{verbatim}
int
is_even(input)
        int input
    CODE:
        RETVAL = (input % 2 == 0);
    OUTPUT:
        RETVAL
\end{verbatim}

aus Beispiel 2 machen? Um jenes zu erreichen, m\"ussen wir eine C Funktion \verb+int is_even(int input)+ definieren.
Wie wir in der Anatomie einer .xs Datei sahen, ist die geeignete Stelle f\"ur jene Definition der erste Abschnitt
einer .xs Datei. In der Tat eine C Funktion

\begin{verbatim}
int
is_even(int arg)
{
    return (arg % 2 == 0);
}
\end{verbatim}

ist wahrscheinlich zuviel des Guten. Etwas so simples wie ein \verb+define+ wird's auch tun:

\begin{verbatim}
#define is_even(arg)    ((arg) % 2 == 0)
\end{verbatim}

Nachdem wir nun jenes als ersten Abschnitt in der .xs Datei haben, wird der Perl spezifische
Teil einfach wie folgendermassen:

\begin{verbatim}
int
is_even(input)
        int input
\end{verbatim}

Diese Technik der Separierung der Schnittstelle vom eigentlichen Code, der die Arbeit tut, hat
gewisse Nachteile: wenn man die Perl Schnittstelle \"andern will, muss man sie an zwei Stellen im Code
\"andern. Wie dem auch sei, es entfernt sehr viel unleserlichen Code und macht den eigentlichen Code
unabh\"angig von den Aufrufkonventionen in Perl. (In der Tat, es ist nichts Perl-spezifisches in der
obigen Beschreibung; eine verschiedene \textbf{xsubpp} Version h\"atte vielleicht dies u.U. zu TCL
oder Python konvertiert.)

\subsection{Weitere XSUB Argumente}
Mit der Vervollst\"andigung des Beispiel 4, ist es nun ein einfaches Bibliotheken zu simulieren,
die im reellen Leben vokommen, deren Schnittstellen wahrscheinlich nicht die fehlerfreiesten sind.
Wir werden nun fortfahren mit einer Erl\"auterung der Argumente, die dem \textbf{xsubpp} Compiler
\"ubergeben werden.
\newline\newline
Wenn du Argumente an Routinen in einer .xs Datei spezifizierst, \"ubergibst du in Tat und Wahrheit
drei St\"ucke an Information f\"ur jedes aufgelistete Argument. Das erste St\"uck ist das Argument
relativ zu den andern (erstes, zweites, etc.). Das zweite ist der Typ des Argument und besteht aus der
Typ Deklaration des Arguments (dh. int, char*, etc.). Das dritte ist die Aufrufkonvention f\"ur das
Argument das an an die Bibliotheksfunktion \"ubergeben wird.
\newline\newline
W\"ahrend Perl Argumente an Funktionen via Referenz \"ubergibt, \"ubergibt sie C als Wert; um eine C
Funktion zu implementieren, die die Daten eines Arguments \"andert, w\"urde das aktuelle Argument
dieser C Funktion ein Zeiger auf Daten sein. Deswegen werden zwei C Funktionen mit den Deklaration

\begin{verbatim}
int string_length(char *s);
int upper_case_char(char *cp);
\end{verbatim}

g\"anzlich verschiedene Semantiken haben: das erste wird wohl ein Array von Zeichen referenziert durch
s inspektieren, zweiteres k\"onnte unmittelbar \verb+cp+ derefenzieren und nur \verb+*cp+ manipulieren
(den R\"uckgabewert als Erfolgsindikator gebrauchend). Von Perl aus w\"urden jene Funktion komplett anders
verwendet werden.
\newline\newline
Diese Information an \textbf{xsubpp} wird \"uberbracht indem \verb+*+ durch \verb+\&+ vor dem Argument ersetzt
wird. \verb+\&+ bedeutet, dass das Argument an eine Bibliotheksfunktion via Addresse \"ubergeben werden soll.
Die beiden obigen Funktionen werden XSUB-ified als

\begin{verbatim}
int
string_length(s)
        char * s

int
upper_case_char(cp)
        char &cp
\end{verbatim}

Beispielsweise, bedenke:

\begin{verbatim}
int
foo(a,b)
        char &a
        char * b
\end{verbatim}

Das erste Perl Argument an diese Funktion w\"urde als char behandelt werden, an die Variable a zugewiesen
werden und die Adresse w\"urde auch an die Funktion \"ubermittelt werden. Das zweite Perl Argument w\"urde
als String Referenz behandelt werden und an die Variable b zugewiesen. Der Wert von b w\"urde an die Funktion
foo weitergereicht werden. Der eigentliche Aufruf der Funktion foo, die \textbf{xsubpp} generiert, w\"urde
folgendermassen ausschauen:

\begin{verbatim}
foo(&a, b);
\end{verbatim}

\textbf{xsubpp} w\"urde folgende Funktionsargumente Liste identisch verarbeiten:

\begin{verbatim}
char    &a
char&a
char    & a
\end{verbatim}

Wie dem auch sei, um das Verst\"andnis zu erleichtern, wird es empfohlen, dass man ein '\&' nebst dem Variabelnamen
platziert, aber separiert vom Variabelntyp und dass man ein '*' nebst dem Variabelntyp platziert, aber separiert vom Variabelnamen
(wie im obigen Aufruf). Indem man dies tut, ist es einfach zu verstehen, was exakt an die C Funktion \"ubergeben wird
- was auch immer in der letzten Spalte ist.
\newline\newline
Du solltest grosse Anstrengungen unternehmen, um zu versuchen der Funktion den Typ der Variable zu \"ubergeben, der erwartet
wird, wenn m\"oglich. Es wird dich vor gr\"osseren Schwierigkeiten bewahren.

\subsection{Der Argument Buffer}

Wenn wir irgendein St\"uck generierten C Code betrachten ausser Beispiel 1, wirst du eine Anzahl an Referenzen an ST(n)
zur Kenntnis nehmen, wo n \"ublicherweise 0 ist. ST ist eigentlich ein Makro, welches zum n'ten Argument auf dem Argument
Buffer zeigt. ST(0) ist foldendermassen das erste Argument auf dem Buffer und deswegen das erste Argument, welches an die
XSUB \"ubergeben wird, ST(1) das zweite Argument, usw.

Wenn du die Argumente an die XSUB in der .xs Datei auflistest, teilt dies \textbf{xsubpp} mit welches Argument mit welchem auf dem
Argument Buffer korrespondiert (dh. das erste aufgelistet ist das erste Argument usw.). Du wirst Schwierigkeiten verursachen,
wenn du sie nicht in der selben Reihenfolge auflisten in der die Funktion sie erwartet.
\newline\newline
Die eigentlichen Werte auf dem Argument Buffer sind Zeiger zu den \"ubergebenen Werten. Wenn ein Argument als OUTPUT Wert aufgelistet
wird, wird sein korrespondierender Wert auf dem Buffer (dh. ST(0) wenn es das erste Argument war) ge\"andert. Du kannst dies verfizieren
indem du den generierten C Code f\"ur Beispiel 3 begutachtest. Der Code f\"ur die round() XSUB Routine beinhaltet Zeilen, die wie folgt
aussehen:

\begin{verbatim}
double  arg = (double)SvNV(ST(0));
/* Round the contents of the variable arg */
sv_setnv(ST(0), (double)arg);
\end{verbatim}

Die arg Variable wird initial auf den Wert von ST(0) gesetzt und am Ende der Routine wird sie zur\"uck in ST(0) geschrieben.
\newline\newline
XSUBs ist es auch gestattet Listen zu retournieren, nicht nur Skalare. Dies muss realisiert werden indem Buffer Werte ST(0), ST(1), etc.
in einer subtilen Art \& Weise manipuliert werden.
\newline\newline
XSUBs ist es \"uberdies gestattet eine automatische Konversion von Perl Funktionsargumenten zu C Funktionsargumenten zu vermeiden.
Gewisse Leute ziehen manuelle Konversion vor indem sie \verb+ST(i)+ \"uberpr\"ufen sogar in F\"allen, wenn automatische Konversion ausreichend
w\"are, argumentierend das es die Logik eines XSUB Aufruf vereinfacht. Man vergleiche es mit 'XSUBs ausreizen' f\"ur einen \"ahnlichen Gewinn
anhand einer kompletten Separierung der Perl Schnittstelle und des eigentlichen Codes einer XSUB.
\newline\newline
Wenn auch Experten \"uber jene Idiome argumentieren, ein Anf\"anger betreffend den Perl Innereien wird eine L\"osung bevorzugen, welche
so wenig wie m\"oglich Perl-Innereien spezifisch ist, die automatische Konversion und Generation von Aufrufen bevorzugend, wie in
'XSUBs ausreizen'. Diese Herangehensweise hat den zus\"atzlichen Vorteil, dass es den XSUB Verfasser von zuk\"unftigen \"Anderungen
an der Perl API bewahrt.

\subsection{Erweitern der Erweiterung}

Manchmal beabsichtigt man zus\"atzliche Methoden oder Subroutinen zur Verf\"ugung zu stellen, um das Verst\"andnis um die Funktionsweise
der Schnittstelle zwischen Perl und Ihrer Erweiterung zu vereinfachen. Jene Funktionen sollten in der .pm Datei enthalten sein. Ob sie
automatisch geladen werden wenn die Erweiterung geladen wird oder nur wenn sie explizit aufgerufen werden, ist abh\"angig von der Platzierung
der Subroutine Definition in der .pm Datei. Du solltest auch die AutoLoader Dokumentation konsultieren f\"ur einen alternativen Weg um
Subroutinen zu speichern und laden.

\subsection{Dokumentation der Erweiterung}

Es gibt keine Rechtfertigung f\"ur das auslassen der obligaten Dokumentation. Dokumentation geh\"ort \"ublicherweise in die .pm Datei.
Der Inhalt jener Datei wird an pod2man \"ubergeben, die eingebettete Dokumentation wird ins manpage Format konvertiert und im blib
Verzeichnis platziert. Es wird in Perl's manpage Verzeichnis kopiert sobald die Erweiterung installiert wird.
\newline\newline
Man m\"oge Dokumentation und Perl Code innerhalb einer .pm Datei durchmischen. In der Tat, wenn man Methode Autoladen einsetzen will, muss
man dies tun, wie der Kommentar innerhalb der .pm Datei erl\"autert.

\subsection{Installation der Erweiterung}

Einst wenn die Erweiterung komplettiert wurde und alle Tests erfolgreich sind, ist die Installation ein einfaches: man f\"uhre ganz einfach
make install aus. Du wirst entweder Schreibrechte f\"ur die Verzeichnisse ben\"otigen wo Perl installiert wird oder deinen Systemadministrator
fragen m\"ussen, ob er make f\"ur dich ausf\"uhrt.
\newline\newline
Alternativ kann man das exakte Verzeichnis spezifizieren, wo die Dateien der Erweiterungen platziert werden, indem man ein PREFIX=/destination/
directory nach make install anh\"angt. Dies kann sich als sehr n\"utzlich erweisen wenn du eine Erweiterung compilierst, welche eventuell f\"ur mehrere
Systeme ver\"offentlicht wird. Du kannst dann einfach die Dateien im Zielverzeichnis archivieren und sie auf deine Zielsysteme kopieren.

\subsection{Beispiel 5}

In diesem Beispiel werden wir uns noch mehr mit dem Argument Buffer auseinandersetzen. All vorherigen Beispiele haben jeweils nur einen
einzelnen Wert retourniert. Wir kreieren nun eine Erweiterung, welche ein Array retourniert.
\newline\newline
Diese Erweiterung ist sehr UNIX-fokussiert (struct statfs und der statfs Systemaufruf). Wenn du nicht ein Unix System betreibst, kannst
du statfs mit einer Funktion ersetzen, die mehrere Werte retourniert, du kannst Werte einf\"ugen die an den Aufrufer zur\"uckgegeben werden
sollen, oder du kannst schlicht und einfach dieses Beispiel \"uberspringen. Sofern du die XSUB \"anderst, stelle sicher, dass die Tests
angepasst werden, sodass sie den \"Anderungen entsprechen.
\newline\newline
Kehre ins Mytest Verzeichnis zur\"uck und f\"uge folgenden Code dem Ende von Mytest.xs an:

\begin{verbatim}
void
statfs(path)
        char *  path
    INIT:
        int i;
        struct statfs buf;

    PPCODE:
        i = statfs(path, &buf);
        if (i == 0) {
            XPUSHs(sv_2mortal(newSVnv(buf.f_bavail)));
            XPUSHs(sv_2mortal(newSVnv(buf.f_bfree)));
            XPUSHs(sv_2mortal(newSVnv(buf.f_blocks)));
            XPUSHs(sv_2mortal(newSVnv(buf.f_bsize)));
            XPUSHs(sv_2mortal(newSVnv(buf.f_ffree)));
            XPUSHs(sv_2mortal(newSVnv(buf.f_files)));
            XPUSHs(sv_2mortal(newSVnv(buf.f_type)));
            XPUSHs(sv_2mortal(newSVnv(buf.f_fsid[0])));
            XPUSHs(sv_2mortal(newSVnv(buf.f_fsid[1])));
        } else {
            XPUSHs(sv_2mortal(newSVnv(errno)));
        }
\end{verbatim}

Du ben\"otigst ausserdem den folgenden Code am Beginn der .xs Datei, soeben nach dem include der 'XSUB.h' Datei:

\begin{verbatim}
#include <sys/vfs.h>
\end{verbatim}

F\"uge ausserdem folgendes Code Segment der Datei test.pl an und inkrementiere den 1..9 String im BEGIN
Block zu 1..11:

\begin{verbatim}
@a = &Mytest::statfs("/blech");
print ((scalar(@a) == 1 && $a[0] == 2) ? "ok 10\n" : "not ok 10\n");
@a = &Mytest::statfs("/");
print scalar(@a) == 9 ? "ok 11\n" : "not ok 11\n";
\end{verbatim}

\subsection{Neues in diesem Beispiel}

Dieses Beispiel erweckte einige neue Konzepte zum Leben. Wir werden sie sukzessiv betrachten.

\begin{itemize}

\item Die INIT: Direktive enth\"alt Code welcher unmittelbar platziert wird nachdem der Argument Buffer dekodiert wird.
C erlaubt keine Variabelndeklarationen an eigenm\"achtigen Positionen innerhalb einer Funktion, deshalb ist dies
\"ublicherweise der beste Weg um lokale Variabeln, die von der XSUB gebraucht werden, zu deklarieren. (Alternativ,
k\"onnte man die \verb+PPCDOE:+ Sektion g\"anzlich in Klammern fassen und jene Deklarationen oben platzieren.)

\item Diese Routine retourniert auch eine differierende Anzahl an Argumenten basierend auf dem Erfolg oder Miserfolg
des statfs Aufrufs. Sofern ein Fehler vorliegen sollte, wird die Fehlernummer als ein Array mit einem Element
retourniert. Sofern der Aufruf erfolgreich war, wird ein Array mit 9 Elementen retourniert. Da nur ein Argument
an jene Funktion \"ubergeben wird, ben\"otigen wir Platz im Buffer, der die 9 Werte, die retourniert werden,
fassen soll.
\newline\newline
Wir tun dies indem wir die PPCODE: Direktive gebrauchen, statt der CODE: Direktive. Dies teil \textbf{xsubpp} mit,
dass wir die R\"uckgabewerte, die wir auf den Argument Buffer tun, selber verwalten werden.

\item Sofern wir beabsichtigen Werte, welche retourniert werdens sollen, auf den Buffer zu packen, gebrauchen wir eine
Serie von Makros, welche mit XPUSH beginnen. Es existieren f\"unf verschiedene Versionen, um integers, unsigned
integers, doubles, Strings und Perl Skalare auf dem Buffer zu platzieren. In unserem Beispiel, platzierten wir
ein Perl Skalar auf dem Buffer. (Dies ist in der Tat das einzige Makro, welches verwendet werden kann um
mehrfache Werte zu retournieren.)
\newline\newline
Die XPUSH* Makros werden automatisch den R\"uckgabe Buffer erweitern, um einen Overrun zu vermeiden.
Sie platzieren Werte in der Reihenfolge auf dem Buffer wie du es w\"uenschst, sodass es das aufzurufende Programm
sieht.

\item Die Werte, die auf dem R\"uckgabe Buffer platziert werden, sind eigentliche 'sterbliche' SV's. Sie werden
sterblich gemacht, sodass einst die Werte vom aufzurufenden Programm kopiert worden sind, die SV's, welche
die R\"uckgabewerte enthielten, dealloziert werden k\"onnen. W\"aren sie nicht sterblich, w\"urden sie
nachdem die XSUB Routine zur\"uckgekehrt ist weiter existieren, w\"aren aber nicht mehr zug\"anglich.
Das ist ein Speicherleck.

\item W\"aren wir in Geschwindigkeit, nicht in Code Kompaktheit interessiert, w\"urden wir im Erfolgsfalle
nicht \verb+XPUSHs+ Makros gebrauchen, sondern \verb+PUSHs+ Makros; desweiteren w\"urden wir vorg\"angig den Buffer
erweitern bevor wir R\"uckgabewerte darauf platzieren:

\begin{verbatim}
EXTEND(SP, 9);
\end{verbatim}

\item Der Kompromiss ist das man die Anzahl R\"uckgabewerte im voraus kalkulieren muss (obschon \"ubermassig
den Buffer erweiternd wird niemanden ausser der Speicherauslastung selbst schaden).
\newline\newline
\"Ahnlicherweise, im Miserfolgsfalle k\"onnten wir \verb+PUSHs+ verwenden ohne den Buffer zu erweitern: die
Perl Funktionsreferenz zeigt auf eine XSUB auf dem Buffer, folgendermassen ist der Buffer immer gross
genug um mindest ein R\"uckgabewert zu fassen.

\end{itemize}

\subsection{Beispiel 6}

In diesem Beispiel werden wir eine Referenz zu einem Array als Eingabe Parameter akzeptieren und retournieren
eine Referenz zu einem Array mit Hashes. Dies wird die Manipulation komplexer Perl Datentypen von einer XSUB
ausgehend demonstrieren.
\newline\newline
Diese Erweiterung ist irgendwie ausgedacht. Sie basiert auf dem Code des vorherigen Beispiels. Es ruft die statfs
Funktion mehrere Male auf, akzeptiert eine Referenz zu einem Array aus Dateinamen bestehend als Eingabe und
retourniert eine Referenz zu einem Array mit Hashes, welche die Daten f\"ur jedes Dateisystem enth\"alt.
\newline\newline
Kehre zum Mytest Verzeichnis zur\"uck und f\"uge folgenden Code dem Ende von Mytest.xs an:

\begin{verbatim}
SV *
multi_statfs(paths)
        SV * paths
    INIT:
        AV * results;
        I32 numpaths = 0;
        int i, n;
        struct statfs buf;

        if ((!SvROK(paths))
            || (SvTYPE(SvRV(paths)) != SVt_PVAV)
            || ((numpaths = av_len((AV *)SvRV(paths))) < 0))
        {
            XSRETURN_UNDEF;
        }
        results = (AV *)sv_2mortal((SV *)newAV());
    CODE:
        for (n = 0; n <= numpaths; n++) {
            HV * rh;
            STRLEN l;
            char * fn = SvPV(*av_fetch((AV *)SvRV(paths), n, 0), l);

            i = statfs(fn, &buf);
            if (i != 0) {
                av_push(results, newSVnv(errno));
                continue;
            }

            rh = (HV *)sv_2mortal((SV *)newHV());

            hv_store(rh, "f_bavail", 8, newSVnv(buf.f_bavail), 0);
            hv_store(rh, "f_bfree",  7, newSVnv(buf.f_bfree),  0);
            hv_store(rh, "f_blocks", 8, newSVnv(buf.f_blocks), 0);
            hv_store(rh, "f_bsize",  7, newSVnv(buf.f_bsize),  0);
            hv_store(rh, "f_ffree",  7, newSVnv(buf.f_ffree),  0);
            hv_store(rh, "f_files",  7, newSVnv(buf.f_files),  0);
            hv_store(rh, "f_type",   6, newSVnv(buf.f_type),   0);

            av_push(results, newRV((SV *)rh));
        }
        RETVAL = newRV((SV *)results);
    OUTPUT:
        RETVAL
\end{verbatim}

F\"uge auch den folgenden Code dem test.pl hinzu und inkrementiere den 1..11 String im BEGIN
Block zu 1..13.

\begin{verbatim}
$results = Mytest::multi_statfs([ '/', '/blech' ]);
print ((ref $results->[0]) ? "ok 12\n" : "not ok 12\n");
print ((! ref $results->[1]) ? "ok 13\n" : "not ok 13\n");
\end{verbatim}

\subsection{Neues in diesem Beispiel}

Einige neue Konzepte werden hier eingef\"uhrt, wie nachfolgend beschrieben:

\begin{itemize}

\item Diese Funktion gebraucht keine typemap. Stattdessen deklarieren wir sie, sodass sie ein SV* (Skalar)
Parameter akzeptiert und ein SV* Wert retourniert; desweiteren, tragen wir Sorge, dass jene Skalare
innerhalb des Codes ins Leben gerufen werden. Da wir nur ein Wert retournieren, brauchen wir keine
\verb+PPCODE:+ Direktive - stattdessen gebrauchen wir die \verb+CODE:+ und \verb+OUTPUT:+ Direktiven.

\item Wenn wir mit Referenzen zu tun haben, ist es wichtig jenen mit Vorsicht zu begegnen. Der \verb+INIT:+ Block
pr\"uft initial ob \verb+SvROK+ wahr retourniert, was indiziert, dass paths eine g\"ultige Referenz ist.
Es pr\"uft dann ob das Objekt, welches durch paths referenziert wird, ein Array ist, indem es \verb+SvRV+
gebraucht um paths zu dereferenzieren und \verb+SvTYPE+ um den Typ zu bestimmen. Wenn es als Test hinzugef\"ugt
wird, pr\"uft es ob das Array durch paths referenziert ungleich leer ist, indem es die \verb+av_len+ Funktion
gebraucht (welche -1 retourniert, wenn der Array leer ist). Das XSRETURN\_UNDEF Makro wird verwendet
um die XSUB zu verlassen und den undefinierten Wert zu retournieren, sofern all jene drei Bedingungen
nicht zutreffen.

\item Wir manipulieren mehrere Arrays in der XSUB. Nehme zur Kenntnis, dass ein Array intern durch ein
AV* Zeiger repr\"asentiert wird. Die Funktionen und Makros, um Arrays zu manipulieren \"ahneln den
folgenden Perl Funktionen: \verb+av_len+ retourniert den h\"ochsten Index in einem AV*; \verb+av_fetch+ liefert
einen einzelnen Wert aus dem Array zur\"uck, der mit dem \"uberlieferten Index korrespondiert; \verb+av_push+
f\"ugt einen skalaren Wert am Ende des Arrays hinzu, automatisch das Array erweiternd, sofern es 
vonn\"oten ist.

Wir lesen ausdr\"ucklich Pfadnamen einzeln aus dem Eingabe Array und speichern die Resultate in einem
Ausgabe Array in derselben Reihenfolge. Sollte statfs nicht erfolgreich sein, wird anstatt des Wertes
die zugeh\"orige Fehlernummer im Array gespeichert. Sollte statfs erfolgreich sein, wird der Wert
der im Array gespeichert wird eine Referenz auf einen Hash sein, der einige Informationen bzgl.
der statfs Struktur beherbergt.

Den R\"uckgabe Buffer betreffend w\"are es m\"oglich (und ein kleiner Geschwindigkeits Gewinn),
den R\"uckgabe Buffer proaktiv zu erweitern, bevor Werte in ihm gespeichert werden, da wir wissen
wieviele Elemente wir retournieren werden:

\begin{verbatim}
av_extend(results, numpaths);
\end{verbatim}

\item Wir f\"uhren nur eine Hash Operation in dieser Funktion durch, dh. wir speichern einen neuen Skalar
unter einem Schl\"ussel \verb+hv_store+ gebrauchend. Ein Hash wird representiert durch ein HV* Zeiger.
Wie f\"ur Arrays, widerspiegeln die Funktionen um Hashes innerhalb einer XSUB zu manipulieren,
die Funktionalit\"at verf\"ugbar aus Perl.

\item Um einen Zeiger zu erstellen, gebrauchen wir die \verb+newRV+ Funktion. Nehme zur Kenntnis, dass
du ein AV* oder HV* zum Typ SV* (und vielen anderen) casten kannst. Dies erm\"oglicht Ihnen
Zeiger auf Arrays, Hashes und Strings mit derselben Funktion zu kreieren. Hingegen retourniert
die \verb+SvRV+ Funktion immer ein SV*, welches eventuell in den richtigen Typ gecastet werden muss,
sofern es etwas anderes als ein String sein sollte (siehe \verb+SvTYPE+).

\item An dieser Stelle verrichtet xsubpp nur minimale Arbeit - die Differenzen zwischen Mytest.xs
und Mytest.c sind minim.

\end{itemize}

\subsection{Beispiel 7}

Du k\"onntest denken, Dateien an XS zu \"uberreichen w\"are schwierig, mit all jenen Typeglobs
und Sachen. Nun denn, ist es nicht.
\newline\newline
Nehme an, dass wir f\"ur einen merkw\"urdigen Grund einen Wrapper um die standardisierte
C Bibliotheksfunktion \verb+fputs()+ ben\"otigen. Nachfolgend alles was wir brauchen:

\begin{verbatim}
#define PERLIO_NOT_STDIO 0
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include <stdio.h>

int
fputs(s, stream)
        char *          s
        FILE *          stream
\end{verbatim}

Die wahre Arbeit wird durch das Standard typemap verrichtet.
\newline\newline
\textbf{Aber} Du kommst nicht in den Genuss der Feinarbeit, die durch die perlio Schnittstellen getan
wird. Hier wird die stdio Funktion \verb+fputs()+ aufgerufen, welche nichts davon weiss.
\newline\newline
Das Standard typemap offeriert drei Varianten der PerlIO: \verb+InputStream+ (T\_IN), \verb+InOutStream+
(T\_INOUT) und \verb+OutputStream+ (T\_OUT). Eine schlichte PerlIO* wird als T\_INOUT bedacht. Wenn es
dir in deinem Code drauf ankommt (siehe unten f\"ur Gr\"unde), define'n oder typedef'e einer der
spezifischen Namen und verwende jenen als Argument oder Resultatstyp in ihrer XS Datei.
\newline\newline
Das Standard typemap enh\"alt kein PerlIO* vor Perl 5.7, aber es gibt drei Stream Varianten.
Ein PerlIO* direkt verwendet ist nicht abw\"artskompatibel ausser man tut die eigene typemap
zur Verf\"ugung stellen.
\newline\newline
F\"ur Streams die von Perl aus kommen ist der Hauptunterschied, dass \verb+OutputStream+ den Ausgabe PerlIO*
erh\"alt - was u.U. einen Unterschied ausmacht auf einem Socket.
\newline\newline
F\"ur Streams, welche an Perl \"ubergeben werden wird ein neues Filehandle kreiert (dh. ein Zeiger zu
einem neuen Glob) und mit dem zur Verf\"ugung gestellten PerlIO * assoziert. Sollte der lese/schreib
Status der PerlIO * nicht korrekt sein, dann k\"onntest du Fehler oder Warnungen erhalten, sofern
das Filehandle gebraucht wird. Dh. wenn du das PerlIO * als ``w'' \"offnen sollte es \verb+OutputStream+
sein, wenn als ``r'' ge\"offnet \verb+InputStream+.
\newline\newline
Nun nehmen wir an du willst perlio Schnittstellen in deinem XS gebrauchen. Wir verwenden die perlio
\verb+PerlIO_puts()+ Funktion in diesem Beispiel.
\newline\newline
In dem C Abschnitt der XS Datei (oben an der ersten MODULE Zeile) hast du folgendes:

\begin{verbatim}
    #define OutputStream    PerlIO *
or
    typedef PerlIO *        OutputStream;
\end{verbatim}
Und im XS Code:
\begin{verbatim}
int
perlioputs(s, stream)
        char *          s
        OutputStream    stream
    CODE:
        RETVAL = PerlIO_puts(stream, s);
    OUTPUT:
        RETVAL
\end{verbatim}

Wir m\"ussen wir die \verb+CODE+ Sektion gebrauchen, da \verb+PerlIO_puts()+ dieselben Argumente umgekehrt
verglichen mit \verb+fputs()+ enth\"alt, und wir die Argumente als selbiges behalten wollten.
\newline\newline
Um jenes weiter zu erforschen, m\"ussen wir die stdio \verb+fputs()+ Funktion auf einem PerlIO * gebrauchen.
D.h. wir m\"ussen von dem perlio System ein stdio \verb+FILE *+ anfordern:

\begin{verbatim}
int
perliofputs(s, stream)
        char *          s
        OutputStream    stream
    PREINIT:
        FILE *fp = PerlIO_findFILE(stream);
    CODE:
        if (fp != (FILE*) 0) {
            RETVAL = fputs(s, fp);
        } else {
            RETVAL = -1;
        }
    OUTPUT:
        RETVAL
\end{verbatim}

Bemerkung: \verb+PerlIO_findFILE()+ wird die Schnittstellen absuchen f\"ur eine stdio Schnittstelle. Sollte keine gefunden werden,
wird es \verb+PerlIO_exportFILE()+ aufrufen, um ein neues stdio \verb+FILE+ zu generieren. Rufe nur \verb+PerlIO_exportFILE()+
auf wenn du ein neues \verb+FILE+ ben\"otigst. Es wird nach jedem Aufruf eines generieren und der stdio Schnittstelle \"ubergeben.
Deswegen rufe es nicht mehrmals f\"ur die gleiche Datei auf. \verb+PerlIO()_findFile+ wird die stdio Schnittstelle erhalten
wenn es durch \verb+PerlIO_exportFILE+ generiert wurde.
\newline\newline
Dies trifft nur auf das perlio System zu. F\"ur Versionen vor 5.7 ist \verb+PerlIO_exportFILE()+ \"aquivalent zu \verb+PerlIO_findFILE()+.

\subsection{Problembehebung}

Wie am Anfang dieses Dokument erw\"ahnt, solltest du Probleme mit den Erweiterungsbeispielen haben, siehe
ob nachfolgende Ratschl\"age helfen.

\begin{itemize}

\item In Versionen 5.002 vor der Gamma Version, wird das Test Script in Beispiel 1 nicht ordnungsgem\"ass funktionieren.
Du musst die "use lib" Zeile folgendermassen \"andern:

\begin{verbatim}
use lib './blib';
\end{verbatim}

\item In Versionen 5.002 vor der Version 5.002b1h, wurde die test.pl Datei nicht automatisch durch h2xs erzeugt. Dies bedeutet,
dass du nicht einfach make test ausf\"uhren kannst, um das Test Script auszuf\"uhren. Du musst die folgende Zeile
vor der ``use extension'' Anweisung platzieren:

\begin{verbatim}
use lib './blib';
\end{verbatim}

\item In Versionen 5.000 und 5.001, wirst du statt der obig ersichtlichen Zeile, folgende Zeile gebrauchen m\"ussen:

\begin{verbatim}
BEGIN { unshift(@INC, "./blib") }
\end{verbatim}

\item Dieses Dokument nimmt an das die ausf\"uhrbare Datei namens ``perl'' Perl Version 5 ist. Einige Systeme haben Perl Version 5
eventuell als ``perl5'' installiert.

\end{itemize}

\section{Siehe auch}

F\"ur weiterf\"uhrende Informationen, ziehe perlguts, perlapi, perlxs, perlmod und perlpod zu Rate.

\section{Autor}

Jeff Okamato \emph{okamoto@corp.hp.com}
\newline\newline
Begutachtet und assistiert durch Dean Roehrich, Ilya Zakharevich, Andreas Koenig und Tim Bunce.
\newline\newline
PerlIO Sachen hinzugef\"ugt durch Lupe Christoph mit einiger Verbesserung durch Nick Ing-Simmons.
\newline\newline
\"Ubersetzt durch Steven Schubiger.

\section{Letzte \"Anderung}

2002/05/08

\end{document}
