Dies ist der Befehl perlxs, der beim kostenlosen Hosting-Anbieter OnWorks mit einer unserer zahlreichen kostenlosen Online-Workstations wie Ubuntu Online, Fedora Online, dem Windows-Online-Emulator oder dem MAC OS-Online-Emulator ausgeführt werden kann
PROGRAMM:
NAME/FUNKTION
perlxs - Referenzhandbuch für die XS-Sprache
BESCHREIBUNG
Einleitung
XS ist ein Schnittstellenbeschreibungsdateiformat, das zum Erstellen einer Erweiterungsschnittstelle zwischen verwendet wird
Perl- und C-Code (oder eine C-Bibliothek), den man mit Perl verwenden möchte. Die XS-Schnittstelle ist
Mit der Bibliothek kombiniert, um eine neue Bibliothek zu erstellen, die dann entweder dynamisch sein kann
geladen oder statisch in Perl verknüpft. Die XS-Schnittstellenbeschreibung wird im XS geschrieben
Sprache und ist die Kernkomponente der Perl-Erweiterungsschnittstelle.
Bevor Sie XS schreiben, lesen Sie den Abschnitt „VORSICHTSHINWEISE“ weiter unten.
An XSUB bildet die Grundeinheit der XS-Schnittstelle. Nach Zusammenstellung durch die xsubpp
Compiler läuft jedes XSUB auf eine C-Funktionsdefinition hinaus, die die Verbindung dazwischen herstellt
Perl-Aufrufkonventionen und C-Aufrufkonventionen.
Der Glue-Code ruft die Argumente aus dem Perl-Stack ab und konvertiert diese Perl-Werte in die
Formate, die von einer C-Funktion erwartet werden, rufen Sie diese C-Funktion auf und übergeben Sie die Rückgabewerte der
C-Funktion zurück zu Perl. Rückgabewerte können hierbei ein herkömmlicher C-Rückgabewert oder ein beliebiges C sein
Funktionsargumente, die als Ausgabeparameter dienen können. Diese Rückgabewerte können übergeben werden
zurück zu Perl, indem Sie sie entweder auf den Perl-Stack legen oder die Argumente ändern
von der Perl-Seite bereitgestellt.
Das Obige ist eine etwas vereinfachte Ansicht dessen, was wirklich passiert. Da Perl mehr erlaubt
Dank der flexibleren Aufrufkonventionen als C können XSUBs in der Praxis viel mehr leisten, beispielsweise Überprüfungen
Eingabeparameter für die Gültigkeit, Auslösen von Ausnahmen (oder Zurückgeben einer Undef-/Leerliste), wenn die
Der Rückgabewert der C-Funktion weist auf einen Fehler hin und ruft basierend darauf verschiedene C-Funktionen auf
Anzahl und Art der Argumente, Bereitstellung einer objektorientierten Schnittstelle usw.
Natürlich könnte man solchen Glue-Code auch direkt in C schreiben. Dies wäre jedoch mühsam
Aufgabe, insbesondere wenn man Kleber für mehrere C-Funktionen schreiben muss und/oder einer dies nicht tut
Ich bin mit der Perl-Stack-Disziplin und anderen solchen Geheimnissen ausreichend vertraut. XS kommt zum
Rettung hier: Anstatt diesen Kleber-C-Code in Langschrift zu schreiben, kann man einen weiteren schreiben
prägnante Kurzschrift Beschreibung von dem, was durch den Kleber gemacht werden soll, und lassen Sie den XS-Compiler
xsubpp Erledige den Rest.
Die XS-Sprache ermöglicht es, die Zuordnung zwischen der Verwendung der C-Routine und zu beschreiben
wie die entsprechende Perl-Routine verwendet wird. Es ermöglicht auch die Erstellung von Perl-Routinen
die direkt in C-Code übersetzt werden und nicht mit einem bereits vorhandenen C in Zusammenhang stehen
Funktion. In Fällen, in denen die C-Schnittstelle mit der Perl-Schnittstelle übereinstimmt, wird die XSUB
Die Deklaration ist nahezu identisch mit der Deklaration einer C-Funktion (im K&R-Stil). In solch
Unter bestimmten Umständen gibt es ein anderes Tool namens „h2xs“, das in der Lage ist, ein ganzes C zu übersetzen
Header-Datei in eine entsprechende XS-Datei, die die Verbindung zu den Funktionen/Makros herstellt
in der Header-Datei beschrieben.
Der XS-Compiler wird aufgerufen xsubpp. Dieser Compiler erstellt die für let erforderlichen Konstrukte
Ein XSUB manipuliert Perl-Werte und erzeugt die Verbindung, die erforderlich ist, damit Perl das XSUB aufrufen kann.
Der Compiler verwendet Typenkarten um zu bestimmen, wie C-Funktionsparameter und Ausgabewerte zugeordnet werden
zu Perl-Werten und zurück. Die Standard-Typemap (die mit Perl geliefert wird) verarbeitet viele gängige Typen
C-Typen. Möglicherweise ist auch eine zusätzliche Typemap erforderlich, um spezielle Strukturen und zu verarbeiten
Typen für die zu verknüpfende Bibliothek. Weitere Informationen zu Typemaps finden Sie unter perlxstypemap.
Eine Datei im XS-Format beginnt mit einem C-Sprachabschnitt, der bis zum ersten „MODULE =" reicht.
Richtlinie. Andere XS-Direktiven und XSUB-Definitionen können dieser Zeile folgen. Die Sprache"
Die in diesem Teil der Datei verwendete Sprache wird üblicherweise als XS-Sprache bezeichnet. xsubpp
erkennt und überspringt POD (siehe Perlpod) sowohl in den Sprachabschnitten C als auch XS
Ermöglicht, dass die XS-Datei eingebettete Dokumentation enthält.
Unter perlxstut finden Sie ein Tutorial zum gesamten Prozess der Erweiterungserstellung.
Hinweis: Bei einigen Erweiterungen bietet das SWIG-System von Dave Beazley möglicherweise deutlich mehr
praktischer Mechanismus zum Erstellen des Extension-Glue-Codes. Sehenhttp://www.swig.org/> für
mehr Informationen.
On Die Rennrad
Viele der folgenden Beispiele konzentrieren sich auf die Erstellung einer Schnittstelle zwischen Perl
und die Funktionen der ONC+ RPC-Bindungsbibliothek. Der rpcb_gettime() Funktion verwendet wird
demonstrieren viele Funktionen der XS-Sprache. Diese Funktion hat zwei Parameter; der erste
ist ein Eingabeparameter und der zweite ist ein Ausgabeparameter. Die Funktion gibt auch a zurück
Statuswert.
bool_t rpcb_gettime(const char *host, time_t *timep);
Von C aus wird diese Funktion mit den folgenden Anweisungen aufgerufen.
#enthalten
bool_t-Status;
time_t timep;
status = rpcb_gettime( "localhost", &timep );
Wenn ein XSUB erstellt wird, um eine direkte Übersetzung zwischen dieser Funktion und Perl anzubieten, dann
Dieses XSUB wird von Perl mit dem folgenden Code verwendet. Der $status und $timep
Variablen enthalten die Ausgabe der Funktion.
RPC verwenden;
$status = rpcb_gettime( "localhost", $timep );
Die folgende XS-Datei zeigt eine XS-Subroutine oder XSUB, die eine Möglichkeit demonstriert
Schnittstelle zum rpcb_gettime() Funktion. Dieses XSUB stellt eine direkte Übersetzung dar
zwischen C und Perl und behält so die Schnittstelle auch von Perl bei. Dieses XSUB wird sein
Wird von Perl mit der oben gezeigten Verwendung aufgerufen. Beachten Sie, dass die ersten drei #include sind
Anweisungen für „EXTERN.h“, „perl.h“ und „XSUB.h“ sind immer vorhanden
Anfang einer XS-Datei. Dieser Ansatz und andere werden später in diesem Dokument erweitert
dokumentieren. Ein #define für „PERL_NO_GET_CONTEXT“ sollte vorhanden sein, um den Interpreter abzurufen
Um den Kontext effizienter zu gestalten, siehe perlguts für Details.
#define PERL_NO_GET_CONTEXT
#include „EXTERN.h“
#include „perl.h“
#include „XSUB.h“
#enthalten
MODUL = RPC PAKET = RPC
bool_t
rpcb_gettime(host,timep)
char *host
time_t &timep
AUSGABE:
Zeitp
Jede Erweiterung von Perl, einschließlich derjenigen, die XSUBs enthalten, sollte über ein Perl-Modul verfügen
dienen als Bootstrap, der die Erweiterung in Perl zieht. Dieses Modul exportiert die
Die Funktionen und Variablen der Erweiterung werden dem Perl-Programm hinzugefügt und verursachen die Erweiterung
XSUBs, die in Perl verknüpft werden sollen. Für die meisten Beispiele wird das folgende Modul verwendet
in diesem Dokument und sollte von Perl aus mit dem Befehl „use“ verwendet werden, wie zuvor gezeigt.
Perl-Module werden später in diesem Dokument ausführlicher erläutert.
Paket RPC;
Exporteur erforderlich;
erfordern DynaLoader;
@ISA = qw(Exporter DynaLoader);
@EXPORT = qw( rpcb_gettime );
Bootstrap-RPC;
1;
In diesem Dokument finden Sie eine Vielzahl von Schnittstellen zum rpcb_gettime() XSUB wird sein
erforscht. Die XSUBs nehmen ihre Parameter in unterschiedlicher Reihenfolge oder unterschiedlich an
Anzahl der Parameter. In jedem Fall ist das XSUB eine Abstraktion zwischen Perl und dem Realen
C rpcb_gettime() Funktion, und das XSUB muss immer sicherstellen, dass die reale rpcb_gettime()
Funktion wird mit den richtigen Parametern aufgerufen. Diese Abstraktion wird es ermöglichen
Programmierer, um eine Perl-ähnlichere Schnittstelle zur C-Funktion zu erstellen.
Die Anatomie of an XSUB
Die einfachsten XSUBs bestehen aus 3 Teilen: einer Beschreibung des Rückgabewerts, dem Namen des
XSUB-Routine und die Namen ihrer Argumente sowie eine Beschreibung der Typen oder Formate der
Argumente.
Das folgende XSUB ermöglicht einem Perl-Programm den Zugriff auf eine aufgerufene C-Bibliotheksfunktion ohne ()dem „Vermischten Geschmack“. Seine
XSUB imitiert die C-Funktion, die ein einzelnes Argument akzeptiert und einen einzelnen Wert zurückgibt.
doppelt
sin (x)
Doppel-X
Optional kann man die Beschreibung der Typen und die Liste der Argumentnamen zusammenführen,
Dies umschreiben als
doppelt
Sünde(doppeltes x)
Dadurch ähnelt dieses XSUB einer ANSI-C-Deklaration. Ein optionales Semikolon ist
nach der Argumentliste zulässig, wie in
doppelt
sin(double x);
Parameter mit C-Zeigertypen können unterschiedliche Semantik haben: C-Funktionen mit ähnlicher
Erklärungen
bool string_looks_as_a_number(char *s);
bool make_char_uppercase(char *c);
werden in absolut inkompatibler Weise verwendet. Parameter für diese Funktionen könnten sein
beschrieben xsubpp so was:
char * s
char &c
Diese beiden XS-Deklarationen entsprechen dem C-Typ „char*“, haben jedoch unterschiedliche
Semantik, siehe „Der & Unäre Operator“.
Es ist sinnvoll anzunehmen, dass der Indirektionsoperator „*“ als Teil betrachtet werden sollte
des Typs und des Adressoperators „&“ sollten als Teil der Variablen betrachtet werden. Sehen
perlxstypemap für weitere Informationen zum Umgang mit Qualifizierern und unären Operatoren in C-Typen.
Der Funktionsname und der Rückgabetyp müssen in separaten Zeilen stehen und sollten bündig sein
linksbündig.
FALSCH RICHTIG
doppelt sin(x) doppelt
doppeltes x sin(x)
Doppel-X
Der Rest der Funktionsbeschreibung kann eingerückt oder linksbündig sein. Die folgende
Das Beispiel zeigt eine Funktion, deren Körper nach links ausgerichtet ist. Die meisten Beispiele in diesem Dokument werden dies tun
Den Text zur besseren Lesbarkeit einrücken.
RICHTIG
doppelt
sin (x)
Doppel-X
Kompliziertere XSUBs können viele andere Abschnitte enthalten. Jeder Abschnitt eines XSUB beginnt
mit dem entsprechenden Schlüsselwort, z. B. INIT: oder CLEANUP:. Allerdings die ersten beiden Zeilen
eines XSUB enthalten immer die gleichen Daten: Beschreibungen des Rückgabetyps und die Namen von
die Funktion und ihre Parameter. Was unmittelbar darauf folgt, gilt als
ein INPUT:-Abschnitt, sofern er nicht ausdrücklich mit einem anderen Schlüsselwort gekennzeichnet ist. (Siehe „Die Eingabe:
Stichwort".)
Ein XSUB-Abschnitt wird fortgesetzt, bis ein anderes Abschnittsstartschlüsselwort gefunden wird.
Die Argument Stapeln
Der Perl-Argumentstapel wird zum Speichern der Werte verwendet, die als Parameter an gesendet werden
XSUB und zum Speichern der Rückgabewerte des XSUB. In Wirklichkeit sind alle Perl-Funktionen (einschließlich
Nicht-XSUB-Werte behalten ihre Werte gleichzeitig auf diesem Stapel, wobei jeder auf seinen eigenen Wert beschränkt ist
Bereich der Positionen auf dem Stapel. In diesem Dokument die erste Position auf diesem Stapel
zur aktiven Funktion gehört, wird für diese Funktion als Position 0 bezeichnet.
XSUBs verweisen mit dem Makro auf ihre Stack-Argumente ST(x), Wobei x bezieht sich auf eine Position in
Dieses XSUB ist Teil des Stapels. Position 0 für diese Funktion wäre dem XSUB bekannt als
ST(0). Die eingehenden Parameter und ausgehenden Rückgabewerte des XSUB beginnen immer bei ST(0).
Für viele einfache Fälle ist die xsubpp Der Compiler generiert den für die Verarbeitung erforderlichen Code
Argumentstapel durch Einbetten von Codefragmenten, die in den Typemaps gefunden werden. In komplexeren Fällen
Der Programmierer muss den Code bereitstellen.
Die WIEDERHOLUNG Variable
Die RETVAL-Variable ist eine spezielle C-Variable, die automatisch für Sie deklariert wird. Das C
Der Typ von RETVAL entspricht dem Rückgabetyp der C-Bibliotheksfunktion. Der xsubpp Compiler
deklariert diese Variable in jedem XSUB mit einem nicht „void“-Rückgabetyp. Standardmäßig ist die
Die generierte C-Funktion verwendet RETVAL, um den Rückgabewert der C-Bibliotheksfunktion zu speichern
gerufen werden. In einfachen Fällen wird der Wert von RETVAL eingesetzt ST(0) des Arguments
Stack, wo es von Perl als Rückgabewert des XSUB empfangen werden kann.
Wenn das XSUB den Rückgabetyp „void“ hat, deklariert der Compiler kein RETVAL
Variable für diese Funktion. Bei Verwendung eines PPCODE: Abschnitts keine Manipulation des RETVAL
Wenn eine Variable erforderlich ist, kann der Abschnitt eine direkte Stapelmanipulation verwenden, um Ausgabewerte zu platzieren
auf dem Stapel.
Wenn die PPCODE:-Direktive nicht verwendet wird, sollte der Rückgabewert „void“ nur für Unterprogramme verwendet werden
die keinen Wert zurückgeben, sogar if CODE: Es wird eine Direktive verwendet, die festlegt ST(0) explizit.
In älteren Versionen dieses Dokuments wurde empfohlen, in solchen Fällen den Rückgabewert „void“ zu verwenden. Es
Es wurde festgestellt, dass dies in Fällen, in denen XSUB vorhanden war, zu Segfaults führen konnte wirklich "Leere". Das
Die Praxis ist inzwischen veraltet und wird möglicherweise in einer zukünftigen Version nicht mehr unterstützt. Benutzen Sie die
Rückgabewert „SV *“ in solchen Fällen. (Derzeit enthält „xsubpp“ heuristischen Code, der
versucht, zwischen „wirklich ungültigen“ und „alte Praxis als ungültig deklarierten“ Funktionen zu unterscheiden.
Daher ist Ihr Code dieser Heuristik ausgeliefert, es sei denn, Sie verwenden „SV *“ als Rückgabewert.)
Rückkehr SVs, AVs und HVs bis WIEDERHOLUNG
Wenn Sie RETVAL verwenden, um ein „SV *“ zurückzugeben, steckt etwas Magie dahinter
Szenen, die erwähnt werden sollten. Wenn Sie den Argumentstapel mithilfe von bearbeiten
Wenn Sie beispielsweise ein ST(x)-Makro verwenden, müssen Sie in der Regel besonders auf die Referenzanzahl achten.
(Weitere Informationen zur Referenzanzahl finden Sie unter perlguts.) Um Ihnen das Leben zu erleichtern, gibt es die Typemap
Datei macht „RETVAL“ automatisch sterblich, wenn Sie ein „SV *“ zurückgeben. Und so kam es dass der
Die folgenden zwei XSUBs sind mehr oder weniger gleichwertig:
ungültig
Alpha()
PPCODE:
ST(0) = newSVpv("Hello World",0);
sv_2mortal(ST(0));
XSRÜCKKEHR(1);
SV *
Beta()
CODE:
RETVAL = newSVpv("Hello World",0);
AUSGABE:
WIEDERHOLUNG
Dies ist sehr nützlich, da es normalerweise die Lesbarkeit verbessert. Während dies für einen „SV“ gut funktioniert
*“ ist es leider nicht so einfach, „AV *“ oder „HV *“ als Rückgabewert zu haben. Sie sollte
schreiben können:
EIN V *
array ()
CODE:
RETVAL = newAV();
/* etwas mit RETVAL machen */
AUSGABE:
WIEDERHOLUNG
Aber aufgrund eines nicht behebbaren Fehlers (die Behebung würde viele vorhandene CPAN-Module beschädigen) im
In der Typemap-Datei wird der Referenzzähler von „AV *“ nicht ordnungsgemäß dekrementiert. Und so kam es dass der
Das obige XSUB würde bei jedem Aufruf Speicher verlieren. Das gleiche Problem besteht für „HV
*“, „CV *“ und „SVREF“ (was auf eine skalare Referenz hinweist, nicht auf ein allgemeines „SV *“). In XS
Code auf Perls ab Perl 5.16, Sie können die Typemaps für jede davon überschreiben
Typen mit einer Version, die Refcounts ordnungsgemäß verarbeitet. Tun Sie dies in Ihrem Abschnitt „TYPEMAP“.
AV* T_AVREF_REFCOUNT_FIXED
um die reparierte Variante zu erhalten. Aus Gründen der Abwärtskompatibilität mit älteren Perl-Versionen
Sie können stattdessen den Referenzzähler manuell verringern, wenn Sie einen der Referenzen zurückgeben
oben genannte Typen mit „sv_2mortal“:
EIN V *
array ()
CODE:
RETVAL = newAV();
sv_2mortal((SV*)RETVAL);
/* etwas mit RETVAL machen */
AUSGABE:
WIEDERHOLUNG
Denken Sie daran, dass Sie dies für einen „SV*“ nicht tun müssen. Die Referenzdokumentation für alle
Kern-Typemaps finden Sie in perlxstypemap.
Die MODULE Stichwort (Keyword)
Das Schlüsselwort MODULE wird verwendet, um den XS-Code zu starten und das Paket des anzugeben
Funktionen, die definiert werden. Der gesamte Text vor dem ersten MODULE-Schlüsselwort ist
Wird als C-Code betrachtet und mit entferntem POD an die Ausgabe weitergeleitet, ansonsten jedoch
unberührt. Jedes XS-Modul verfügt über eine Bootstrap-Funktion, die zum Einbinden der XSUBs verwendet wird
in Perl. Der Paketname dieser Bootstrap-Funktion stimmt mit dem Wert der letzten überein
MODULE-Anweisung in den XS-Quelldateien. Der Wert von MODULE sollte immer erhalten bleiben
Konstante innerhalb derselben XS-Datei, obwohl dies nicht erforderlich ist.
Das folgende Beispiel startet den XS-Code und platziert alle Funktionen in einem Paket
mit dem Namen RPC.
MODUL = RPC
Die PAKET Stichwort (Keyword)
Wenn Funktionen innerhalb einer XS-Quelldatei in Pakete unterteilt werden müssen, muss das PACKAGE
Schlüsselwort sollte verwendet werden. Dieses Schlüsselwort wird mit dem Schlüsselwort MODULE verwendet und muss folgen
unmittelbar danach, wenn es verwendet wird.
MODUL = RPC PAKET = RPC
[XS-Code im Paket RPC]
MODUL = RPC-PAKET = RPCB
[XS-Code im Paket RPCB]
MODUL = RPC PAKET = RPC
[XS-Code im Paket RPC]
Derselbe Paketname kann mehr als einmal verwendet werden, sodass nicht zusammenhängender Code möglich ist. Das
ist nützlich, wenn Sie ein stärkeres Ordnungsprinzip haben als Paketnamen.
Obwohl dieses Schlüsselwort optional ist und in einigen Fällen redundante Informationen liefert
sollte immer verwendet werden. Dieses Schlüsselwort stellt sicher, dass die XSUBs in der gewünschten Reihenfolge angezeigt werden
Paket.
Die PRÄFIX Stichwort (Keyword)
Das Schlüsselwort PREFIX bezeichnet Präfixe, die aus der Perl-Funktion entfernt werden sollen
Namen. Wenn die C-Funktion „rpcb_gettime()“ ist und der PREFIX-Wert „rpcb_“ ist, dann ist Perl
wird diese Funktion als „gettime()“ sehen.
Dieses Schlüsselwort sollte bei Verwendung dem Schlüsselwort PACKAGE folgen. Wenn PACKAGE nicht verwendet wird, dann
PREFIX sollte dem Schlüsselwort MODULE folgen.
MODUL = RPC PREFIX = rpc_
MODUL = RPC PAKET = RPCB PREFIX = rpcb_
Die AUSGABE: Stichwort (Keyword)
Das Schlüsselwort OUTPUT: gibt an, dass bestimmte Funktionsparameter aktualisiert werden sollen (neu).
Werte, die für Perl sichtbar gemacht werden), wenn das XSUB beendet wird oder dass bestimmte Werte beendet werden sollen
an die aufrufende Perl-Funktion zurückgegeben. Für einfache Funktionen, die keinen CODE haben: oder
PPCODE: Abschnitt, z. B. der ohne () Funktion oben, die RETVAL-Variable wird automatisch verwendet
als Ausgabewert bezeichnet. Für komplexere Funktionen die xsubpp Compiler benötigt
helfen bei der Bestimmung, welche Variablen Ausgabevariablen sind.
Dieses Schlüsselwort wird normalerweise als Ergänzung zum Schlüsselwort CODE: verwendet. Die RETVAL-Variable
wird nicht als Ausgabevariable erkannt, wenn das Schlüsselwort CODE: vorhanden ist. Die Ausgabe:
Das Schlüsselwort wird in dieser Situation verwendet, um dem Compiler mitzuteilen, dass RETVAL tatsächlich eine Ausgabe ist
variabel.
Das Schlüsselwort OUTPUT: kann auch verwendet werden, um anzugeben, dass Funktionsparameter ausgegeben werden
Variablen. Dies kann erforderlich sein, wenn ein Parameter innerhalb der Funktion geändert wurde
und der Programmierer möchte, dass das Update von Perl gesehen wird.
bool_t
rpcb_gettime(host,timep)
char *host
time_t &timep
AUSGABE:
Zeitp
Das Schlüsselwort OUTPUT: ermöglicht auch die Zuordnung eines Ausgabeparameters zu einem passenden Teil
von Code statt einer Typemap.
bool_t
rpcb_gettime(host,timep)
char *host
time_t &timep
AUSGABE:
timep sv_setnv(ST(1), (double)timep);
xsubpp gibt ein automatisches „SvSETMAGIC()“ für alle Parameter im OUTPUT-Abschnitt des aus
XSUB, außer RETVAL. Dies ist das normalerweise gewünschte Verhalten, da es ordnungsgemäß funktioniert
Aufrufen von „Set“-Magie für Ausgabeparameter (erforderlich für Hash- oder Array-Elementparameter).
die erstellt werden müssen, wenn sie nicht existierten). Wenn dieses Verhalten aus irgendeinem Grund nicht auftritt
Falls gewünscht, kann der Abschnitt OUTPUT eine Zeile „SETMAGIC: DISABLE“ enthalten, um ihn für den zu deaktivieren
Die restlichen Parameter finden Sie im Abschnitt OUTPUT. Ebenso kann „SETMAGIC: ENABLE“ lauten
Wird verwendet, um es für den Rest des OUTPUT-Abschnitts wieder zu aktivieren. Weitere Informationen finden Sie unter perlguts
Details über „Set“-Magie.
Die KEINE LEISTUNG Stichwort (Keyword)
Der NO_OUTPUT kann als erster Token des XSUB platziert werden. Dieses Schlüsselwort weist darauf hin
während die C-Subroutine, für die wir eine Schnittstelle bereitstellen, einen nicht „void“-Rückgabetyp hat, den return
Der Wert dieser C-Subroutine sollte nicht von der generierten Perl-Subroutine zurückgegeben werden.
Wenn dieses Schlüsselwort vorhanden ist, wird die „RETVAL-Variable“ erstellt und im generierten Aufruf an
Das Unterprogramm, dem diese Variable zugewiesen ist, aber der Wert dieser Variablen geht nicht
zur Verwendung im automatisch generierten Code.
Dieses Schlüsselwort ist nur dann sinnvoll, wenn der vom Benutzer bereitgestellte Zugriff auf „RETVAL“ erfolgt
Code. Es ist besonders nützlich, eine Funktionsschnittstelle Perl-ähnlicher zu gestalten
wenn der C-Rückgabewert nur ein Fehlerzustandsindikator ist. Zum Beispiel,
NO_OUTPUT int
delete_file(char *name)
POSTANRUF:
if (RETVAL != 0)
croak("Fehler %d beim Löschen der Datei '%s'", RETVAL, name);
Hier gibt die generierte XS-Funktion bei Erfolg nichts zurück und wird dies auch tun die () mit
aussagekräftige Fehlermeldung bei Fehler.
Die CODE: Stichwort (Keyword)
Dieses Schlüsselwort wird in komplizierteren XSUBs verwendet, die eine besondere Behandlung für C erfordern
Funktion. Die RETVAL-Variable ist weiterhin deklariert, wird jedoch nicht zurückgegeben, sofern dies nicht der Fall ist
im Abschnitt OUTPUT: angegeben.
Das folgende XSUB ist für eine C-Funktion, die eine besondere Behandlung ihrer Parameter erfordert.
Zuerst wird die Perl-Nutzung erläutert.
$status = rpcb_gettime( "localhost", $timep );
Es folgt das XSUB.
bool_t
rpcb_gettime(host,timep)
char *host
time_t timep
CODE:
RETVAL = rpcb_gettime( host, &timep );
AUSGABE:
Zeitp
WIEDERHOLUNG
Die DRIN: Stichwort (Keyword)
Das Schlüsselwort INIT: ermöglicht das Einfügen der Initialisierung in das XSUB vor dem Compiler
generiert den Aufruf der C-Funktion. Im Gegensatz zum obigen Schlüsselwort CODE: ist dies bei diesem Schlüsselwort der Fall
hat keinen Einfluss auf die Art und Weise, wie der Compiler RETVAL verarbeitet.
bool_t
rpcb_gettime(host,timep)
char *host
time_t &timep
DRIN:
printf("# Host ist %s\n", host );
AUSGABE:
Zeitp
Eine weitere Verwendung des INIT:-Abschnitts besteht darin, vor einem Aufruf die Voraussetzungen zu prüfen
die C-Funktion:
lang Lang
lldiv(a,b)
lange lange a
lang lang b
DRIN:
if (a == 0 && b == 0)
XSRETURN_UNDEF;
wenn (b == 0)
croak("lldiv: kann nicht durch 0 geteilt werden");
Die NO_INIT Stichwort (Keyword)
Das Schlüsselwort NO_INIT wird verwendet, um anzuzeigen, dass ein Funktionsparameter nur als Parameter verwendet wird
Ausgabewert. Der xsubpp Der Compiler generiert normalerweise Code, um die Werte aller zu lesen
Funktionsparameter aus dem Argumentstapel und weisen Sie sie bei der Eingabe C-Variablen zu
die Funktion. NO_INIT teilt dem Compiler mit, dass einige Parameter für die Ausgabe verwendet werden
statt zur Eingabe und dass sie verarbeitet werden, bevor die Funktion beendet wird.
Das folgende Beispiel zeigt eine Variation davon rpcb_gettime() Funktion. Diese Funktion
verwendet die timep-Variable nur als Ausgabevariable und kümmert sich nicht um deren Anfangsvariable
Inhalt.
bool_t
rpcb_gettime(host,timep)
char *host
time_t &timep = NO_INIT
AUSGABE:
Zeitp
Die TYPKARTE: Stichwort (Keyword)
Ab Perl 5.16 können Sie Typemaps anstelle von oder in Ihren XS-Code einbetten
Ergänzung zu Typemaps in einer separaten Datei. Es werden mehrere solcher eingebetteten Typemaps vorhanden sein
werden in der Reihenfolge ihres Erscheinens im XS-Code verarbeitet und wie lokale Typemap-Dateien verwendet
Vorrang vor der Standard-Typemap haben, können die eingebetteten Typemaps vorherige überschreiben
Definitionen der Strophen TYPEMAP, INPUT und OUTPUT. Die Syntax für eingebettete Typemaps lautet
TYPEMAP: <
... Ihr Typemap-Code hier ...
KLICKEN SIE HIER
Dabei muss das Schlüsselwort „TYPEMAP“ in der ersten Spalte einer neuen Zeile erscheinen.
Einzelheiten zum Schreiben von Typemaps finden Sie unter perlxstypemap.
Initialisierung Funktion Parameter
C-Funktionsparameter werden normalerweise mit ihren Werten aus dem Argumentstapel initialisiert
(die wiederum die Parameter enthält, die von Perl an das XSUB übergeben wurden). Der
Typemaps enthalten die Codesegmente, die zum Übersetzen der Perl-Werte in C verwendet werden
Parameter. Dem Programmierer ist es jedoch gestattet, die Typemaps zu überschreiben und bereitzustellen
alternativer (oder zusätzlicher) Initialisierungscode. Der Initialisierungscode beginnt mit dem ersten
„=“, „;“ oder „+“ in einer Zeile im Abschnitt INPUT:. Die einzige Ausnahme tritt auf, wenn dieses „;“
beendet die Zeile, dann ist dieses „;“ wird stillschweigend ignoriert.
Der folgende Code zeigt, wie Initialisierungscode für Funktionsparameter bereitgestellt wird.
Der Initialisierungscode wird vom Compiler in doppelte Anführungszeichen gesetzt, bevor er hinzugefügt wird
an die Ausgabe also alles, was wörtlich interpretiert werden sollte [hauptsächlich „$“, „@“ oder „\\“]
müssen durch Backslashes geschützt werden. Die Variablen $var, $arg und $type können wie in verwendet werden
Typkarten.
bool_t
rpcb_gettime(host,timep)
char *host = (char *)SvPV_nolen($arg);
time_t &timep = 0;
AUSGABE:
Zeitp
Dies sollte nicht zur Bereitstellung von Standardwerten für Parameter verwendet werden. Normalerweise würde man es verwenden
Dies ist der Fall, wenn ein Funktionsparameter zuvor von einer anderen Bibliotheksfunktion verarbeitet werden muss
verwendet werden. Standardparameter werden im nächsten Abschnitt behandelt.
Beginnt die Initialisierung mit „=“, dann wird es in der Deklaration für die Eingabe ausgegeben
Variable, die die von der Typemap bereitgestellte Initialisierung ersetzt. Wenn die Initialisierung
beginnt mit ";" oder „+“, dann wird es ausgeführt, nachdem alle Eingabevariablen eingegeben wurden
erklärt. Im ";" In diesem Fall ist die Initialisierung, die normalerweise von der Typemap bereitgestellt wird, nicht der Fall
durchgeführt. Im Fall „+“ enthält die Deklaration für die Variable das
Initialisierung aus der Typemap. Für die wirklich Seltenen steht eine globale Variable, %v, zur Verfügung
Fall, in dem Informationen aus einer Initialisierung in einer anderen Initialisierung benötigt werden.
Hier ist ein wirklich obskures Beispiel:
bool_t
rpcb_gettime(host,timep)
time_t &timep; /* \$v{timep}=@{[$v{timep}=$arg]} */
char *host + SvOK($v{timep}) ? SvPV_nolen($arg) : NULL;
AUSGABE:
Zeitp
Das im obigen Beispiel verwendete Konstrukt „\$v{timep}=@{[$v{timep}=$arg]}“ hat eine Zweifachheit
Zweck: Erstens, wenn diese Zeile verarbeitet wird xsubpp, das Perl-Snippet „$v{timep}=$arg“
ausgewertet wird. Zweitens wird der Text des ausgewerteten Snippets in das generierte C ausgegeben
Datei (innerhalb eines C-Kommentars)! Während der Verarbeitung der Zeile „char *host“ wird $arg ausgewertet
zu ST(0) und $v{timep} wird zu ausgewertet ST(1).
Standard Parameter Werte
Standardwerte für XSUB-Argumente können durch Einfügen einer Zuweisungsanweisung angegeben werden
die Parameterliste. Der Standardwert kann eine Zahl, eine Zeichenfolge oder eine spezielle Zeichenfolge sein
„NO_INIT“. Standardwerte sollten immer nur für die Parameter ganz rechts verwendet werden.
Um das XSUB zu ermöglichen rpcb_gettime() um einen Standard-Hostwert für die Parameter zu haben
XSUB könnte neu angeordnet werden. Das XSUB ruft dann das Reale auf rpcb_gettime() funktionieren mit
die Parameter in der richtigen Reihenfolge. Dieses XSUB kann von Perl aus mit beiden aufgerufen werden
folgende Aussagen:
$status = rpcb_gettime( $timep, $host );
$status = rpcb_gettime( $timep );
Das XSUB sieht wie der folgende Code aus. Zum Aufrufen wird ein CODE:-Block verwendet
echt rpcb_gettime() Funktion mit den Parametern in der richtigen Reihenfolge für diese Funktion.
bool_t
rpcb_gettime(timep,host="localhost")
char *host
time_t timep = NO_INIT
CODE:
RETVAL = rpcb_gettime( host, &timep );
AUSGABE:
Zeitp
WIEDERHOLUNG
Die VOREINIT: Stichwort (Keyword)
Das Schlüsselwort PREINIT: ermöglicht die Deklaration zusätzlicher Variablen unmittelbar vor oder nach dem
Es werden Deklarationen der Parameter aus dem Abschnitt INPUT: ausgegeben.
Wenn eine Variable innerhalb eines CODE:-Abschnitts deklariert wird, folgt sie jedem vorhandenen Typemap-Code
für die Eingabeparameter ausgegeben. Dies kann dazu führen, dass die Deklaration nach C endet
Code, der ein C-Syntaxfehler ist. Ähnliche Fehler können bei einem expliziten „;“-Typ oder auftreten
Es wird die Initialisierung von Parametern vom Typ „+“ verwendet (siehe „Funktionsparameter initialisieren“).
Das Deklarieren dieser Variablen in einem INIT:-Abschnitt hilft nicht.
In solchen Fällen wird die Deklaration einer zusätzlichen Variablen zusammen mit Deklarationen erzwungen
Wenn Sie andere Variablen verwenden möchten, platzieren Sie die Deklaration in einem PREINIT:-Abschnitt. Das Schlüsselwort PREINIT:
kann innerhalb eines XSUB einmal oder mehrmals verwendet werden.
Die folgenden Beispiele sind gleichwertig, aber wenn der Code komplexe Typzuordnungen verwendet, dann
Das erste Beispiel ist sicherer.
bool_t
rpcb_gettime(timep)
time_t timep = NO_INIT
VOREINIT:
char *host = "localhost";
CODE:
RETVAL = rpcb_gettime( host, &timep );
AUSGABE:
Zeitp
WIEDERHOLUNG
In diesem speziellen Fall würde ein INIT:-Schlüsselwort denselben C-Code generieren wie PREINIT:
Stichwort. Ein weiteres richtiges, aber fehleranfälliges Beispiel:
bool_t
rpcb_gettime(timep)
time_t timep = NO_INIT
CODE:
char *host = "localhost";
RETVAL = rpcb_gettime( host, &timep );
AUSGABE:
Zeitp
WIEDERHOLUNG
Eine andere Möglichkeit, „host“ zu deklarieren, besteht darin, einen C-Block im CODE:-Abschnitt zu verwenden:
bool_t
rpcb_gettime(timep)
time_t timep = NO_INIT
CODE:
{
char *host = "localhost";
RETVAL = rpcb_gettime( host, &timep );
}
AUSGABE:
Zeitp
WIEDERHOLUNG
Es besteht die Möglichkeit, vor der Verarbeitung der Typemap-Einträge zusätzliche Deklarationen abzugeben
Sehr praktisch in den Fällen, in denen Typemap-Konvertierungen einen globalen Status manipulieren:
Mein Objekt
mutieren(o)
VOREINIT:
MyState st = global_state;
EINGANG:
MyObject o;
AUFRÄUMEN:
reset_to(global_state, st);
Hier nehmen wir an, dass die Konvertierung in „MyObject“ im Abschnitt „INPUT:“ und von „MyObject“ erfolgt
Durch die Verarbeitung von RETVAL wird eine globale Variable „global_state“ geändert. Nach diesen Umbauten
ausgeführt werden, stellen wir den alten Wert von „global_state“ wieder her (um Speicherlecks zu vermeiden, z
Beispiel).
Es gibt eine andere Möglichkeit, Klarheit gegen Kompaktheit einzutauschen: INPUT-Abschnitte ermöglichen die Deklaration von
C-Variablen, die nicht in der Parameterliste eines Unterprogramms erscheinen. Also das obige
Code für mutieren() kann umgeschrieben werden als
Mein Objekt
mutieren(o)
MyState st = global_state;
MyObject o;
AUFRÄUMEN:
reset_to(global_state, st);
und der Code für rpcb_gettime() kann umgeschrieben werden als
bool_t
rpcb_gettime(timep)
time_t timep = NO_INIT
char *host = "localhost";
C_ARGS:
host, &timep
AUSGABE:
Zeitp
WIEDERHOLUNG
Die UMFANG: Stichwort (Keyword)
Das Schlüsselwort SCOPE: ermöglicht die Aktivierung des Scopings für ein bestimmtes XSUB. Wenn aktiviert, wird die
XSUB ruft automatisch ENTER und LEAVE auf.
Zur Unterstützung potenziell komplexer Typzuordnungen, wenn ein von einem XSUB verwendeter Typemap-Eintrag enthält
Wenn Sie einen Kommentar wie „/*scope*/“ eingeben, wird das Scoping automatisch für dieses XSUB aktiviert.
So aktivieren Sie die Bereichsbestimmung:
ANWENDUNGSBEREICH: AKTIVIEREN
So deaktivieren Sie die Bereichsbestimmung:
ANWENDUNGSBEREICH: DEAKTIVIEREN
Die EINGANG: Stichwort (Keyword)
Die Parameter des XSUB werden in der Regel unmittelbar nach der Eingabe des XSUB ausgewertet. Der
Das Schlüsselwort INPUT: kann verwendet werden, um die Auswertung dieser Parameter etwas später zu erzwingen. Der
INPUT: Das Schlüsselwort kann innerhalb eines XSUB mehrfach verwendet werden und kann zum Auflisten eines oder verwendet werden
mehr Eingabevariablen. Dieses Schlüsselwort wird mit dem Schlüsselwort PREINIT: verwendet.
Das folgende Beispiel zeigt, wie der Eingabeparameter „timep“ spät, nach einem ausgewertet werden kann
VOREINIT.
bool_t
rpcb_gettime(host,timep)
char *host
VOREINIT:
time_t tt;
EINGANG:
time_t timep
CODE:
RETVAL = rpcb_gettime( host, &tt );
timep = tt;
AUSGABE:
Zeitp
WIEDERHOLUNG
Das nächste Beispiel zeigt jeden Eingabeparameter, der spät ausgewertet wird.
bool_t
rpcb_gettime(host,timep)
VOREINIT:
time_t tt;
EINGANG:
char *host
VOREINIT:
char *h;
EINGANG:
time_t timep
CODE:
h = Wirt;
RETVAL = rpcb_gettime( h, &tt );
timep = tt;
AUSGABE:
Zeitp
WIEDERHOLUNG
Da INPUT-Abschnitte die Deklaration von C-Variablen ermöglichen, die nicht im Parameter erscheinen
Liste einer Unterroutine, dies kann wie folgt abgekürzt werden:
bool_t
rpcb_gettime(host,timep)
time_t tt;
char *host;
char *h = Host;
time_t timep;
CODE:
RETVAL = rpcb_gettime( h, &tt );
timep = tt;
AUSGABE:
Zeitp
WIEDERHOLUNG
(Wir haben unser Wissen genutzt, dass die Eingabekonvertierung für „char *“ eine „einfache“ ist, also „host“
wird in der Deklarationszeile initialisiert und unsere Zuweisung „h = host“ wird ebenfalls nicht ausgeführt
früh. Ansonsten müsste man in einem CODE: oder INIT: die Zuweisung „h = host“ haben:
Sektion.)
Die IN/OUTLIST/IN_OUTLIST/OUT/IN_OUT Stichwörter
In der Liste der Parameter für ein XSUB kann man den Parameternamen das voranstellen
Schlüsselwörter „IN“/„OUTLIST“/„IN_OUTLIST“/„OUT“/„IN_OUT“. Das Schlüsselwort „IN“ ist die Standardeinstellung
Andere Schlüsselwörter geben an, wie sich die Perl-Schnittstelle von der C-Schnittstelle unterscheiden soll.
Parameter, denen die Schlüsselwörter „OUTLIST“/„IN_OUTLIST“/„OUT“/„IN_OUT“ vorangestellt sind, gelten als
Wird von der C-Unterroutine verwendet Zeiger. Die Schlüsselwörter „OUTLIST“/„OUT“ geben an, dass die C
Die Unterroutine überprüft nicht den Speicher, auf den dieser Parameter zeigt, sondern schreibt ihn durch
diesen Zeiger, um zusätzliche Rückgabewerte bereitzustellen.
Parameter, denen das Schlüsselwort „OUTLIST“ vorangestellt ist, erscheinen nicht in der Verwendungssignatur des
generierte Perl-Funktion.
Parameter mit vorangestelltem „IN_OUTLIST“/„IN_OUT“/„OUT“ do erscheinen als Parameter für Perl
Funktion. Mit Ausnahme der „OUT“-Parameter werden diese Parameter in die umgewandelt
entsprechenden C-Typ, dann werden Zeiger auf diese Daten als Argumente an den C übergeben
Funktion. Es wird erwartet, dass die C-Funktion diese Zeiger durchschreibt.
Die Rückgabeliste der generierten Perl-Funktion besteht aus dem C-Rückgabewert von
Funktion (es sei denn, das XSUB hat den Rückgabetyp „void“ oder es wurde das Schlüsselwort „NO_OUTPUT“ verwendet)
gefolgt von allen Parametern „OUTLIST“ und „IN_OUTLIST“ (in der Reihenfolge ihres Erscheinens).
Bei der Rückkehr vom XSUB wird der Perl-Parameter „IN_OUT“/„OUT“ so geändert, dass er Folgendes hat:
Von der C-Funktion geschriebene Werte.
Zum Beispiel ein XSUB
ungültig
day_month(OUTLIST-Tag, IN unix_time, OUTLIST-Monat)
int Tag
int unix_time
int Monat
sollte von Perl als verwendet werden
my ($day, $month) = day_month(time);
Die C-Signatur der entsprechenden Funktion sollte sein
void day_month(int *day, int unix_time, int *month);
Die Schlüsselwörter „IN“/„OUTLIST“/„IN_OUTLIST“/„IN_OUT“/„OUT“ können im ANSI-Stil gemischt werden
Erklärungen, wie in
ungültig
day_month(OUTLIST int Tag, int unix_time, OUTLIST int Monat)
(hier wird das optionale Schlüsselwort „IN“ weggelassen).
Die „IN_OUT“-Parameter sind identisch mit den mit „The & Unary“ eingeführten Parametern
Operator“ und in den Abschnitt „OUTPUT:“ eingefügt (siehe „Das OUTPUT:-Schlüsselwort“)
„IN_OUTLIST“-Parameter sind sehr ähnlich, der einzige Unterschied besteht darin, dass der Wert C
Funktion, die über den Zeiger schreibt, würde den Perl-Parameter nicht ändern, sondern in den eingefügt werden
Ausgabeliste.
Die Parameter „OUTLIST“/„OUT“ unterscheiden sich von den Parametern „IN_OUTLIST“/„IN_OUT“ nur durch die
Der Anfangswert des Perl-Parameters wird nicht gelesen (und nicht an die C-Funktion übergeben).
- was stattdessen etwas Müll erzeugt). Beispielsweise kann die gleiche C-Funktion wie oben verwendet werden
Schnittstelle mit as
void day_month(OUT int day, int unix_time, OUT int monatlich);
or
ungültig
day_month(Tag, unix_time, Monat)
int &day = NO_INIT
int unix_time
int &month = NO_INIT
AUSGABE:
Tag
Monat
Allerdings wird die generierte Perl-Funktion im sehr C-ähnlichen Stil aufgerufen:
mein ($Tag, $Monat);
day_month($day, time, $month);
Die „Länge(NAME)“ Stichwort (Keyword)
Wenn eines der Eingabeargumente der C-Funktion die Länge eines Zeichenfolgenarguments „NAME“ hat,
man kann den Namen des Längenarguments durch „length(NAME)“ im XSUB ersetzen
Erklärung. Dieses Argument muss weggelassen werden, wenn die generierte Perl-Funktion aufgerufen wird.
Z.B,
ungültig
dump_chars(char *s, kurzes l)
{
kurz n = 0;
while (n < l) {
printf("s[%d] = \"\\%#03o\"\n", n, (int)s[n]);
n++;
}
}
MODUL = x PAKET = x
void dump_chars(char *s, kurze Länge(n))
sollte als „dump_chars($string)“ aufgerufen werden.
Diese Direktive wird nur mit ANSI-Funktionsdeklarationen unterstützt.
Variable Länge Parameter Listen
XSUBs können Parameterlisten variabler Länge haben, indem in der Datei ein Auslassungszeichen „(...)“ angegeben wird
Parameterliste. Diese Verwendung der Auslassungspunkte ähnelt der in ANSI C. Die
Der Programmierer kann durch Untersuchung die Anzahl der an XSUB übergebenen Argumente ermitteln
die Variable „items“, die die xsubpp Compiler-Zubehör für alle XSUBs. Indem Sie dies nutzen
Mechanismus kann man ein XSUB erstellen, das eine Liste von Parametern unbekannter Länge akzeptiert.
Die Gastgeber Parameter für die rpcb_gettime() XSUB kann optional sein, sodass die Auslassungspunkte verwendet werden können
um anzuzeigen, dass das XSUB eine variable Anzahl von Parametern annimmt. Perl sollte dazu in der Lage sein
um dieses XSUB mit einer der folgenden Anweisungen aufzurufen.
$status = rpcb_gettime( $timep, $host );
$status = rpcb_gettime( $timep );
Es folgt der XS-Code mit Auslassungspunkten.
bool_t
rpcb_gettime(timep, ...)
time_t timep = NO_INIT
VOREINIT:
char *host = "localhost";
CODE:
if( Elemente > 1 )
host = (char *)SvPV_nolen(ST(1));
RETVAL = rpcb_gettime( host, &timep );
AUSGABE:
Zeitp
WIEDERHOLUNG
Die C_ARGS: Stichwort (Keyword)
Das Schlüsselwort C_ARGS: ermöglicht die Erstellung von XSUBS, die eine andere Aufrufsequenz haben
Perl als von C, ohne dass ein CODE:- oder PPCODE:-Abschnitt geschrieben werden muss. Der Inhalt der
C_ARGS: Der Absatz wird ohne Änderung als Argument an die aufgerufene C-Funktion übergeben.
Angenommen, eine C-Funktion ist als deklariert
symbolic nth_derivative(int n, symbolic function, int flags);
und dass die Standardflags in einer globalen C-Variablen „default_flags“ gespeichert werden. Nehme an, dass
Sie möchten eine Schnittstelle erstellen, die als aufgerufen wird
$second_deriv = $function->nth_derivative(2);
Deklarieren Sie dazu das XSUB als
symbolisch
nth_derivative(Funktion, n)
symbolische Funktion
int n
C_ARGS:
n, Funktion, default_flags
Die PPCODE: Stichwort (Keyword)
Das Schlüsselwort PPCODE: ist eine alternative Form des Schlüsselworts CODE: und wird verwendet, um das mitzuteilen
xsubpp Compiler, dass der Programmierer den Code zur Steuerung des Argumentstapels bereitstellt
für die Rückgabewerte der XSUBs. Gelegentlich möchte man, dass ein XSUB eine Liste von zurückgibt
Werte und nicht ein einzelner Wert. In diesen Fällen muss man PPCODE: und dann verwenden
Schieben Sie die Werteliste explizit auf den Stapel. Die Schlüsselwörter PPCODE: und CODE: sollten
nicht zusammen innerhalb desselben XSUB verwendet werden.
Der eigentliche Unterschied zwischen den Abschnitten PPCODE: und CODE: liegt in der Initialisierung von „SP“.
Makro (was für die steht Strom Perl-Stapelzeiger) und im Umgang mit Daten auf
den Stapel bei der Rückkehr von einem XSUB. In CODE: Abschnitten behält SP den Wert bei, der war
beim Eintrag in das XSUB: SP steht auf dem Funktionszeiger (der auf den letzten Parameter folgt).
In PPCODE: Abschnitte SP wird rückwärts an den Anfang der Parameterliste verschoben, die
Ermöglicht „PUSH*()“-Makros, Ausgabewerte an der Stelle zu platzieren, an der Perl sie erwartet
das XSUB kehrt zu Perl zurück.
Der generierte Trailer für einen CODE:-Abschnitt stellt sicher, dass die Anzahl der Rückgabewerte Perl
sehen wird, ist entweder 0 oder 1 (abhängig von der „Leerheit“ des Rückgabewerts des C
Funktion und Heuristik, die in „Die RETVAL-Variable“ erwähnt werden). Der Trailer wurde für a erstellt
PPCODE: Abschnitt basiert auf der Anzahl der Rückgabewerte und auf der Häufigkeit von „SP“
wurde durch „[X]PUSH*()“-Makros aktualisiert.
Beachten Sie, dass die Makros ST(i), „XST_m*()“ und „XSRETURN*()“ in CODE:-Abschnitten gleich gut funktionieren
und PPCODE: Abschnitte.
Das folgende XSUB ruft das C auf rpcb_gettime() Funktion und gibt ihre beiden Ausgaben zurück
Werte, Zeit und Status als einzelne Liste in Perl übertragen.
ungültig
rpcb_gettime(host)
char *host
VOREINIT:
time_t timep;
bool_t-Status;
PPCODE:
status = rpcb_gettime( host, &timep );
EXTEND(SP, 2);
PUSHs(sv_2mortal(newSViv(status)));
PUSHs(sv_2mortal(newSViv(timep)));
Beachten Sie, dass der Programmierer den C-Code bereitstellen muss, der erforderlich ist, um die Realität zu erhalten
rpcb_gettime() Funktion aufgerufen und die Rückgabewerte richtig platziert werden
Argumentstapel.
Der Rückgabetyp „void“ für diese Funktion teilt dem mit xsubpp Compiler, der RETVAL
Variable wird nicht benötigt oder verwendet und sollte nicht erstellt werden. In den meisten Szenarien ist die
Der Rückgabetyp „void“ sollte mit der PPCODE:-Direktive verwendet werden.
Die ERWEITERN() Das Makro wird verwendet, um auf dem Argumentstapel Platz für zwei Rückgabewerte zu schaffen. Der
PPCODE: Direktive verursacht das xsubpp Compiler zum Erstellen eines Stapelzeigers, der als „SP“ verfügbar ist.
und es ist dieser Zeiger, der im verwendet wird ERWEITERN() Makro. Die Werte sind dann
mit dem auf den Stapel geschoben PUSHs() Makro.
Jetzt die rpcb_gettime() Die Funktion kann von Perl aus mit der folgenden Anweisung verwendet werden.
($status, $timep) = rpcb_gettime("localhost");
Achten Sie beim Umgang mit Ausgabeparametern mit einem PPCODE-Abschnitt darauf, dass Sie mit „Set“-Magie umgehen
richtig. Einzelheiten zur „Set“-Magie finden Sie unter Perlguts.
Rückkehr Undef Und leer Listen
Gelegentlich möchte der Programmierer einfach „undef“ oder eine leere Liste zurückgeben, wenn a
Funktion schlägt fehl und nicht ein separater Statuswert. Der rpcb_gettime() Funktionsangebote
genau diese Situation. Wenn die Funktion erfolgreich ist, möchten wir, dass sie die Zeit zurückgibt
und wenn es fehlschlägt, möchten wir, dass undef zurückgegeben wird. Im folgenden Perl-Code wird die
Der Wert von $timep ist entweder undef oder es handelt sich um eine gültige Zeit.
$timep = rpcb_gettime( "localhost" );
Das folgende XSUB verwendet den Rückgabetyp „SV *“ nur als Mnemonik und verwendet einen CODE:-Block
um dem Compiler anzuzeigen, dass der Programmierer den gesamten erforderlichen Code bereitgestellt hat. Der
sv_newmortal() Der Aufruf initialisiert den Rückgabewert auf undef und macht ihn zum Standardwert
Rückgabewert.
SV *
rpcb_gettime(host)
char * Host
VOREINIT:
time_t timep;
bool_t x;
CODE:
ST(0) = sv_newmortal();
if( rpcb_gettime( host, &timep ) )
sv_setnv( ST(0), (double)timep);
Das nächste Beispiel zeigt, wie man ein explizites Undef in den Rückgabewert einfügt.
sollte die Notwendigkeit bestehen.
SV *
rpcb_gettime(host)
char * Host
VOREINIT:
time_t timep;
bool_t x;
CODE:
if( rpcb_gettime( host, &timep ) ){
ST(0) = sv_newmortal();
sv_setnv( ST(0), (double)timep);
}
sonst {
ST(0) = &PL_sv_undef;
}
Um eine leere Liste zurückzugeben, muss man einen PPCODE:-Block verwenden und darf dann keine Rückgabewerte weitergeben
den Stack.
ungültig
rpcb_gettime(host)
char *host
VOREINIT:
time_t timep;
PPCODE:
if( rpcb_gettime( host, &timep ) )
PUSHs(sv_2mortal(newSViv(timep)));
sonst {
/* Nichts auf den Stapel verschoben, also leer
* Liste wird implizit zurückgegeben. */
}
Einige Leute neigen möglicherweise dazu, ein explizites „return“ in das obige XSUB aufzunehmen, anstatt
Die Kontrolle bis zum Ende fallen lassen. In solchen Situationen sollte „XSRETURN_EMPTY“ lauten
stattdessen verwendet. Dadurch wird sichergestellt, dass der XSUB-Stack richtig angepasst ist. Konsultieren
perlapi für andere „XSRETURN“-Makros.
Da „XSRETURN_*“-Makros auch mit CODE-Blöcken verwendet werden können, kann man dies umschreiben
Beispiel als:
int
rpcb_gettime(host)
char *host
VOREINIT:
time_t timep;
CODE:
RETVAL = rpcb_gettime( host, &timep );
if (RETVAL == 0)
XSRETURN_UNDEF;
AUSGABE:
WIEDERHOLUNG
Tatsächlich kann man diese Prüfung auch in einen Postcall:-Abschnitt einfügen. Zusammen mit PREINIT:
Vereinfachungen führt dies zu:
int
rpcb_gettime(host)
char *host
time_t timep;
POSTANRUF:
if (RETVAL == 0)
XSRETURN_UNDEF;
Die ERFORDERN: Stichwort (Keyword)
Das Schlüsselwort REQUIRE: wird verwendet, um die Mindestversion von anzugeben xsubpp Compiler erforderlich
um das XS-Modul zu kompilieren. Ein XS-Modul, das die folgende Anweisung enthält, wird
kompilieren nur mit xsubpp Version 1.922 oder höher:
ERFORDERLICH: 1.922
Die AUFRÄUMEN: Stichwort (Keyword)
Dieses Schlüsselwort kann verwendet werden, wenn vor einem XSUB spezielle Bereinigungsprozeduren erforderlich sind
endet. Wenn das Schlüsselwort CLEANUP: verwendet wird, muss es auf einen beliebigen CODE: oder OUTPUT: folgen.
Blöcke, die im XSUB vorhanden sind. Der für den Bereinigungsblock angegebene Code lautet
als letzte Anweisungen im XSUB hinzugefügt.
Die POSTANRUF: Stichwort (Keyword)
Dieses Schlüsselwort kann verwendet werden, wenn ein XSUB spezielle Prozeduren erfordert, die nach dem C ausgeführt werden
Unterprogrammaufruf wird durchgeführt. Wenn das Schlüsselwort POSTCALL: verwendet wird, muss es vor OUTPUT stehen:
und CLEANUP: Blöcke, die im XSUB vorhanden sind.
Siehe Beispiele in „Das Schlüsselwort NO_OUTPUT“ und „Rückgabe von Undef- und leeren Listen“.
Der POSTCALL:-Block macht wenig Sinn, wenn der C-Unterprogrammaufruf von bereitgestellt wird
Benutzer, indem Sie entweder den Abschnitt CODE: oder PPCODE: angeben.
Die STIEFEL: Stichwort (Keyword)
Das Schlüsselwort BOOT: wird verwendet, um Code zur Bootstrap-Funktion der Erweiterung hinzuzufügen. Der
Die Bootstrap-Funktion wird von generiert xsubpp Compiler und enthält normalerweise die Anweisungen
erforderlich, um XSUBs bei Perl zu registrieren. Mit dem Schlüsselwort BOOT: kann der Programmierer es erkennen
Der Compiler kann der Bootstrap-Funktion zusätzliche Anweisungen hinzufügen.
Dieses Schlüsselwort kann jederzeit nach dem ersten MODULE-Schlüsselwort verwendet werden und sollte auf a erscheinen
Zeile für sich. Die erste Leerzeile nach dem Schlüsselwort beendet den Codeblock.
STIEFEL:
# Die folgende Meldung wird gedruckt, wenn die
# Bootstrap-Funktion wird ausgeführt.
printf("Hallo vom Bootstrap!\n");
Die VERSIONSPRÜFUNG: Stichwort (Keyword)
Das Schlüsselwort VERSIONCHECK: entspricht xsubpp„-versioncheck“ und „-noversioncheck“
Optionen. Dieses Schlüsselwort überschreibt die Befehlszeilenoptionen. Die Versionsprüfung wird aktiviert durch
Standard. Wenn die Versionsprüfung aktiviert ist, versucht das XS-Modul, dies zu überprüfen
Die Version entspricht der Version des PM-Moduls.
So aktivieren Sie die Versionsprüfung:
VERSIONSPRÜFUNG: AKTIVIEREN
So deaktivieren Sie die Versionsprüfung:
VERSIONSPRÜFUNG: DEAKTIVIEREN
Beachten Sie, dass die Version des PM-Moduls eine NV (eine Gleitkommazahl) ist
stringifiziert mit einem möglichen Verlust an Präzision (derzeit auf neun Dezimalstellen zerhackt)
sodass es möglicherweise nicht mehr mit der Version des XS-Moduls übereinstimmt. Zitieren der $VERSION
Wenn lange Versionsnummern verwendet werden, empfiehlt sich die Deklaration, daraus einen String zu machen.
Die PROTOTYPEN: Stichwort (Keyword)
Das Schlüsselwort PROTOTYPES: entspricht xsubppDie Optionen „-prototypes“ und „-noprototypes“ von
Dieses Schlüsselwort überschreibt die Befehlszeilenoptionen. Prototypen sind standardmäßig aktiviert. Wenn
Prototypen sind aktiviert. XSUBs erhalten Perl-Prototypen. Dieses Schlüsselwort darf verwendet werden
mehrmals in einem XS-Modul, um Prototypen für verschiedene Teile des zu aktivieren und zu deaktivieren
Modul.
So aktivieren Sie Prototypen:
PROTOTYPEN: AKTIVIEREN
So deaktivieren Sie Prototypen:
PROTOTYPEN: DEAKTIVIEREN
Die PROTOTYP: Stichwort (Keyword)
Dieses Schlüsselwort ähnelt dem obigen Schlüsselwort PROTOTYPES:, kann jedoch zum Erzwingen verwendet werden xsubpp
einen bestimmten Prototyp für das XSUB zu verwenden. Dieses Schlüsselwort überschreibt alle anderen Prototypen
Optionen und Schlüsselwörter, wirkt sich jedoch nur auf das aktuelle XSUB aus. Konsultieren Sie „Prototypen“ in perlsub
für Informationen über Perl-Prototypen.
bool_t
rpcb_gettime(timep, ...)
time_t timep = NO_INIT
PROTOTYP: $;$
VOREINIT:
char *host = "localhost";
CODE:
if( Elemente > 1 )
host = (char *)SvPV_nolen(ST(1));
RETVAL = rpcb_gettime( host, &timep );
AUSGABE:
Zeitp
WIEDERHOLUNG
Wenn die Prototypen aktiviert sind, können Sie sie lokal für ein bestimmtes XSUB deaktivieren, wie im
folgendes Beispiel:
ungültig
rpcb_gettime_noproto()
PROTOTYP: DEAKTIVIEREN
...
Die AKA: Stichwort (Keyword)
Das Schlüsselwort ALIAS: ermöglicht es einem XSUB, zwei oder mehr eindeutige Perl-Namen zu haben und zu wissen, welche
dieser Namen wurde verwendet, als er aufgerufen wurde. Die Perl-Namen können mit vollständig qualifiziert sein
Paketnamen. Jeder Alias erhält einen Index. Der Compiler richtet eine Variable namens ein
„ix“, die den Index des verwendeten Alias enthalten. Beim Aufruf des XSUB mit
sein deklarierter Name „ix“ wird 0 sein.
Im folgenden Beispiel werden hierfür die Aliase „FOO::gettime()“ und „BAR::getit()“ erstellt
Funktion.
bool_t
rpcb_gettime(host,timep)
char *host
time_t &timep
AKA:
FOO::gettime = 1
BAR::getit = 2
DRIN:
printf("# ix = %d\n", ix );
AUSGABE:
Zeitp
Die ÜBERLAST: Stichwort (Keyword)
Anstatt eine überladene Schnittstelle mit reinem Perl zu schreiben, können Sie auch OVERLOAD verwenden
Schlüsselwort, um zusätzliche Perl-Namen für Ihre Funktionen zu definieren (wie das Schlüsselwort ALIAS:).
über). Allerdings müssen die überladenen Funktionen mit drei Parametern definiert werden (außer
für die nomethod() Funktion, die vier Parameter benötigt). Wenn eine Funktion das hat
OVERLOAD: Schlüsselwort, mehrere zusätzliche Zeilen werden in der von generierten C-Datei definiert
xsubpp, um sich bei der Überladungsmagie zu registrieren.
Da gesegnete Objekte tatsächlich als RVs gespeichert werden, ist es sinnvoll, die Typemap zu verwenden
Funktionen zur Vorverarbeitung von Parametern und zum Extrahieren des tatsächlichen SV, der im gesegneten RV gespeichert ist.
Sehen Sie sich das Beispiel für T_PTROBJ_SPECIAL unten an.
Um das Schlüsselwort OVERLOAD: zu verwenden, erstellen Sie eine XS-Funktion, die drei Eingabeparameter akzeptiert (
oder verwenden Sie die C-Stil-Definition „...“ wie folgt:
SV *
cmp (lobj, robj, swap)
My_Module_obj lobj
My_Module_obj robj
IV-Tausch
ÜBERLADUNG: cmp <=>
{ /* Funktion hier definiert */}
In diesem Fall überlastet die Funktion beide drei Vergleichsoperatoren. Für
Bei allen Überladungsvorgängen mit Nicht-Alpha-Zeichen müssen Sie den Parameter ohne eingeben
Anführungszeichen, Trennung mehrerer Überladungen durch Leerzeichen. Beachten Sie, dass „“ (die stringify
Überlastung) sollte als \"\" (d. h. mit Escapezeichen) eingegeben werden.
Die ZURÜCKGREIFEN: Stichwort (Keyword)
Zusätzlich zum Schlüsselwort OVERLOAD, wenn Sie steuern müssen, wie Perl automatisch fehlende Elemente generiert
Bei überladenen Operatoren können Sie das Schlüsselwort FALLBACK im Modul-Header-Abschnitt festlegen, z. B
Dies:
MODUL = RPC PAKET = RPC
FALLBACK: WAHR
...
wobei FALLBACK einen der drei Werte TRUE, FALSE oder UNDEF annehmen kann. Wenn Sie nicht einstellen
Wenn Sie bei Verwendung von OVERLOAD einen beliebigen FALLBACK-Wert verwenden, ist der Standardwert UNDEF. FALLBACK wird nicht verwendet, außer
wenn eine oder mehrere Funktionen, die OVERLOAD verwenden, definiert wurden. Siehe „Fallback“ in
Überladung für weitere Details.
Die SCHNITTSTELLE: Stichwort (Keyword)
Dieses Schlüsselwort deklariert das aktuelle XSUB als Bewahrer der angegebenen Aufrufsignatur. Wenn
Wenn diesem Schlüsselwort Text folgt, handelt es sich um eine Liste von Funktionen, die dieses Schlüsselwort enthalten
Signatur und sollte an das aktuelle XSUB angehängt werden.
Wenn Sie beispielsweise über 4 C-Funktionen verfügen multiplizieren(), teilen(), hinzufügen(), subtrahieren() alle haben
die Unterschrift:
symbolisch f(symbolisch, symbolisch);
Sie können dafür sorgen, dass sie alle dasselbe XSUB verwenden, indem Sie Folgendes tun:
symbolisch
interface_s_ss(arg1, arg2)
symbolisches arg1
symbolisches arg2
SCHNITTSTELLE:
multiplizieren dividieren
addieren subtrahieren
(Dies ist der vollständige XSUB-Code für 4 Perl-Funktionen!) Vier generierte Perl-Funktionen teilen sich
Namen mit entsprechenden C-Funktionen.
Der Vorteil dieses Ansatzes im Vergleich zum Schlüsselwort ALIAS: besteht darin, dass dies nicht erforderlich ist
Wenn Sie eine Switch-Anweisung codieren, weiß jede Perl-Funktion (die dasselbe XSUB verwendet) welche C
Funktion, die aufgerufen werden soll. Zusätzlich kann man noch eine Zusatzfunktion anbringen Rest() at
Laufzeit durch Verwendung
CV *mycv = newXSproto("Symbolic::remainder",
XS_Symbolic_interface_s_ss, __FILE__, "$$");
XSINTERFACE_FUNC_SET(mycv, rest);
sagen wir, von einem anderen XSUB. (In diesem Beispiel wird davon ausgegangen, dass es kein INTERFACE_MACRO gab:
Abschnitt, sonst muss man statt „XSINTERFACE_FUNC_SET“ etwas anderes verwenden, siehe
den nächsten Abschnitt.)
Die SCHNITTSTELLE_MAKRO: Stichwort (Keyword)
Mit diesem Schlüsselwort kann man eine SCHNITTSTELLE auf andere Weise zum Extrahieren einer Funktion definieren
Zeiger von einem XSUB. Der Text, der diesem Schlüsselwort folgt, sollte den Namen von Makros angeben
was einen Funktionszeiger extrahieren/setzen würde. Das Extraktormakro erhält den Rückgabetyp,
„CV*“ und „XSANY.any_dptr“ für diesen „CV*“. Das Setter-Makro erhält cv und das
Funktionszeiger.
Der Standardwert ist „XSINTERFACE_FUNC“ und „XSINTERFACE_FUNC_SET“. Ein INTERFACE-Schlüsselwort
mit einer leeren Funktionsliste kann weggelassen werden, wenn das Schlüsselwort INTERFACE_MACRO verwendet wird.
Angenommen, im vorherigen Beispiel funktionieren Zeiger für multiplizieren(), teilen(), hinzufügen(),
subtrahieren() werden in einem globalen C-Array „fp[]“ mit den Offsets „multiply_off“ gespeichert.
„divide_off“, „add_off“, „subtract_off“. Dann kann man es nutzen
#define XSINTERFACE_FUNC_BYOFFSET(ret,cv,f) \
((XSINTERFACE_CVT_ANON(ret))fp[CvXSUBANY(cv).any_i32])
#define XSINTERFACE_FUNC_BYOFFSET_set(cv,f) \
CvXSUBANY(cv).any_i32 = CAT2( f, _off )
im C-Abschnitt,
symbolisch
interface_s_ss(arg1, arg2)
symbolisches arg1
symbolisches arg2
SCHNITTSTELLE_MAKRO:
XSINTERFACE_FUNC_BYOFFSET
XSINTERFACE_FUNC_BYOFFSET_set
SCHNITTSTELLE:
multiplizieren dividieren
addieren subtrahieren
im XSUB-Bereich.
Die INHALT: Stichwort (Keyword)
Mit diesem Schlüsselwort können andere Dateien in das XS-Modul gezogen werden. Die anderen Dateien haben möglicherweise
XS-Code. INCLUDE: kann auch zum Ausführen eines Befehls zum Generieren des abzurufenden XS-Codes verwendet werden
in das Modul ein.
Die Datei Rpcb1.xsh enthält unsere Funktion „rpcb_gettime()“:
bool_t
rpcb_gettime(host,timep)
char *host
time_t &timep
AUSGABE:
Zeitp
Das XS-Modul kann INCLUDE: verwenden, um diese Datei hineinzuziehen.
ENTHALTEN: Rpcb1.xsh
Wenn auf die Parameter des Schlüsselworts INCLUDE: ein senkrechter Strich („|“) folgt, dann der Compiler
interpretiert die Parameter als Befehl. Diese Funktion ist zugunsten von leicht veraltet
die „INCLUDE_COMMAND:“-Direktive, wie unten dokumentiert.
INCLUDE: cat Rpcb1.xsh |
Verwenden Sie dies nicht, um Perl auszuführen: „INCLUDE: perl |“ wird das Perl ausführen, das zufällig das ist
zuerst in Ihrem Pfad und nicht unbedingt das gleiche Perl, das zum Ausführen von „xsubpp“ verwendet wird. Sehen
„Das Schlüsselwort INCLUDE_COMMAND:“.
Die INCLUDE_COMMAND: Stichwort (Keyword)
Führt den bereitgestellten Befehl aus und fügt seine Ausgabe in das aktuelle XS-Dokument ein.
„INCLUDE_COMMAND“ weist dem $^X-Token eine besondere Bedeutung zu, da es dasselbe Perl ausführt
Interpreter, der „xsubpp“ ausführt:
INCLUDE_COMMAND: cat Rpcb1.xsh
INCLUDE_COMMAND: $^X -e ...
Die FALL: Stichwort (Keyword)
Das Schlüsselwort CASE: ermöglicht es einem XSUB, mehrere unterschiedliche Teile zu haben, wobei jeder Teil als fungiert
ein virtuelles XSUB. CASE: ist gierig und wenn es verwendet wird, müssen es alle anderen XS-Schlüsselwörter sein
in einem CASE: enthalten. Das bedeutet, dass dem ersten CASE: im XSUB und nichts vorangehen darf
alles, was auf den letzten CASE: folgt, ist in diesem Fall enthalten.
Ein CASE: könnte über einen Parameter des XSUB, über die Variable „ix“ ALIAS: umschalten (siehe „The
ALIAS: Schlüsselwort“) oder möglicherweise über die Variable „items“ (siehe „Parameter mit variabler Länge“)
Listen"). Der letzte CASE: wird zum Standard Fall, wenn es nicht mit a verknüpft ist
bedingt. Das folgende Beispiel zeigt CASE umgeschaltet über „ix“ mit einer Funktion
„rpcb_gettime()“ mit einem Alias „x_gettime()“. Wenn die Funktion aufgerufen wird als
„rpcb_gettime()“ seine Parameter sind die üblichen „(char *host, time_t *timep)“, aber wenn die
Funktion wird als „x_gettime()“ aufgerufen, ihre Parameter werden umgekehrt, „(time_t *timep, char
*Gastgeber)".
lange
rpcb_gettime(a,b)
FALL: ix == 1
AKA:
x_gettime = 1
EINGANG:
# 'a' ist timep, 'b' ist host
char *b
time_t a = NO_INIT
CODE:
RETVAL = rpcb_gettime( b, &a );
AUSGABE:
a
WIEDERHOLUNG
FALL:
# 'a' ist Host, 'b' ist timep
char *a
time_t &b = NO_INIT
AUSGABE:
b
WIEDERHOLUNG
Diese Funktion kann mit einer der folgenden Anweisungen aufgerufen werden. Beachten Sie den Unterschied
Argumentlisten.
$status = rpcb_gettime( $host, $timep );
$status = x_gettime( $timep, $host );
Die EXPORT_XSUB_SYMBOLS: Stichwort (Keyword)
Das Schlüsselwort EXPORT_XSUB_SYMBOLS: ist wahrscheinlich etwas, das Sie nie brauchen werden. In Perl
In Versionen vor 5.16.0 bewirkt dieses Schlüsselwort keine Wirkung. Ab 5.16 XSUB-Symbole
werden standardmäßig nicht mehr exportiert. Das heißt, es handelt sich um „statische“ Funktionen. Wenn Sie einschließen
EXPORT_XSUB_SYMBOLS: AKTIVIEREN
In Ihrem XS-Code werden die auf diese Zeile folgenden XSUBs nicht als „statisch“ deklariert. Du kannst
Deaktivieren Sie dies später mit
EXPORT_XSUB_SYMBOLS: DEAKTIVIEREN
Dies ist wiederum die Standardeinstellung, die Sie wahrscheinlich nie ändern sollten. Sie können dies nicht verwenden
Schlüsselwort in Perl-Versionen vor 5.16, um XSUBs „statisch“ zu machen.
Die & Einstellig Operator
Zur Feststellung wird der unäre Operator „&“ im Abschnitt INPUT: verwendet xsubpp dass es konvertieren sollte
einen Perl-Wert zu/von C mithilfe des C-Typs links von „&“ erstellen, aber einen Zeiger darauf bereitstellen
Wert, wenn die C-Funktion aufgerufen wird.
Dies ist nützlich, um einen CODE:-Block für eine C-Funktion zu vermeiden, der einen Parameter annimmt
Referenz. Normalerweise sollte der Parameter kein Zeigertyp sein (ein „int“ oder „long“, sondern
kein „int*“ oder „long*“).
Das folgende XSUB generiert falschen C-Code. Der xsubpp Der Compiler wird dies ändern
in Code, der „rpcb_gettime()“ mit den Parametern „(char *host, time_t timep)“ aufruft, aber
Das echte „rpcb_gettime()“ möchte, dass der Parameter „timep“ vom Typ „time_t*“ ist und nicht
„time_t“.
bool_t
rpcb_gettime(host,timep)
char *host
time_t timep
AUSGABE:
Zeitp
Dieses Problem wird durch die Verwendung des Operators „&“ behoben. Der xsubpp Der Compiler wird nun eingeschaltet
Dies in Code, der „rpcb_gettime()“ korrekt mit den Parametern „(char *host, time_t
*timep)". Dies geschieht durch Durchführen des „&“, sodass der Funktionsaufruf so aussieht
„rpcb_gettime(host, &timep)“.
bool_t
rpcb_gettime(host,timep)
char *host
time_t &timep
AUSGABE:
Zeitp
Einsetzen POD, Ihre Nachricht und C Präprozessor Richtlinien
C-Präprozessoranweisungen sind innerhalb von BOOT:, PREINIT: INIT:, CODE:, PPCODE:, zulässig.
POSTCALL: und CLEANUP: Blöcke sowie außerhalb der Funktionen. Kommentare sind erlaubt
irgendwo nach dem Schlüsselwort MODULE. Der Compiler übergibt die Präprozessoranweisungen
bleibt unberührt und entfernt die kommentierten Zeilen. POD-Dokumentation ist jederzeit zulässig
Punkt, sowohl in den Sprachabschnitten C als auch XS. POD muss mit einem „=cut“ abgeschlossen werden
Befehl; Andernfalls wird „xsubpp“ mit einer Fehlermeldung beendet. Es ist sehr unwahrscheinlich, dass ein Mensch
Generierter C-Code wird mit POD verwechselt, da die meisten Einrückungsstile zu Leerzeichen führen
vor jeder Zeile, die mit „=" beginnt. Maschinengenerierte XS-Dateien können in diese Falle tappen
es sei denn, es wird darauf geachtet, dass ein Leerzeichen die Sequenz „\n=" unterbricht.
Kommentare können zu XSUBs hinzugefügt werden, indem ein „#“ als erstes Nicht-Leerzeichen einer Zeile platziert wird.
Es sollte darauf geachtet werden, dass der Kommentar nicht wie eine C-Präprozessoranweisung aussieht.
damit es nicht als solches interpretiert wird. Der einfachste Weg, dies zu verhindern, besteht darin, Leerzeichen einzufügen
vor dem „#“.
Wenn Sie Präprozessordirektiven verwenden, um eine von zwei Versionen einer Funktion auszuwählen, verwenden Sie
#if ... Version1
#else /* ... version2 */
#endif
und nicht
#if ... Version1
#endif
#if ... Version2
#endif
weil sonst xsubpp Ich werde glauben, dass Sie eine doppelte Definition von erstellt haben
Funktion. Fügen Sie außerdem eine Leerzeile vor #else/#endif ein, damit es nicht als Teil gesehen wird
des Funktionskörpers.
Die richtigen XS Mit C + +
Wenn ein XSUB-Name „::“ enthält, wird er als C++-Methode betrachtet. Das generierte Perl
Die Funktion geht davon aus, dass ihr erstes Argument ein Objektzeiger ist. Der Objektzeiger
wird in einer Variablen namens THIS gespeichert. Das Objekt sollte von C++ mit erstellt worden sein
Neu() Funktion und sollte von Perl mit dem gesegnet werden sv_setref_pv() Makro. Der
Die Segnung des Objekts durch Perl kann über eine Typemap erfolgen. Es wird eine Beispiel-Typemap angezeigt
am Ende dieses Abschnitts.
Wenn der Rückgabetyp des XSUB „static“ enthält, wird die Methode als statisch betrachtet
Methode. Es ruft die C++-Funktion mit auf class::method() Syntax. Wenn die Methode ist
nicht statisch, die Funktion wird mit THIS-> aufgerufenMethode() Syntax.
In den nächsten Beispielen wird die folgende C++-Klasse verwendet.
Klassenfarbe {
Öffentlichkeit:
Farbe();
~color();
int blue();
void set_blue( int );
Privatgelände:
int c_blue;
};
Die XSUBs für die Blau() und set_blue() Methoden werden mit dem Klassennamen definiert, aber der
Der Parameter für das Objekt (THIS oder „self“) ist implizit und wird nicht aufgeführt.
int
Farbe blau()
ungültig
color::set_blue( val )
int val
Beide Perl-Funktionen erwarten ein Objekt als ersten Parameter. Im generierten C++
Code heißt das Objekt „THIS“ und der Methodenaufruf wird für dieses Objekt ausgeführt.
Also im C++-Code die Blau() und set_blue() Methoden werden wie folgt aufgerufen:
RETVAL = THIS->blue();
THIS->set_blue( val );
Sie könnten auch eine einzelne get/set-Methode mit einem optionalen Argument schreiben:
int
color::blue( val = NO_INIT )
int val
PROTOTYP $;$
CODE:
if (Elemente > 1)
THIS->set_blue( val );
RETVAL = THIS->blue();
AUSGABE:
WIEDERHOLUNG
Wenn der Name der Funktion lautet DESTROY dann wird die C++-Funktion „delete“ aufgerufen und „THIS“
wird als Parameter angegeben. Der generierte C++-Code für
ungültig
color::DESTROY()
wird so aussehen:
Farbe *THIS = ...; // Initialisiert wie in der Typemap
Lösch das;
Wenn der Name der Funktion lautet neu Dann wird die C++-Funktion „new“ aufgerufen, um eine zu erstellen
dynamisches C++-Objekt. Das XSUB erwartet den Klassennamen, der in einer Variablen gespeichert wird
mit dem Namen „CLASS“, der als erstes Argument angegeben werden soll.
Farbe *
color::new()
Der generierte C++-Code ruft „new“ auf.
RETVAL = neue Farbe();
Im Folgenden finden Sie ein Beispiel für eine Typzuordnung, die für dieses C++-Beispiel verwendet werden könnte.
TYPMAP
Farbe * O_OBJECT
AUSGABE
# Das Perl-Objekt wird in „CLASS“ eingeteilt, was ein sein sollte
# char* mit dem Namen des Pakets für den Segen.
O_OBJECT
sv_setref_pv( $arg, CLASS, (void*)$var );
SPEISUNG
O_OBJECT
if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) )
$var = ($type)SvIV((SV*)SvRV( $arg ));
sonst {
warn("${Package}::$func_name() -- " .
„$var ist keine gesegnete SV-Referenz“);
XSRETURN_UNDEF;
}
Schnittstelle Strategie
Beim Entwerfen einer Schnittstelle zwischen Perl und einer C-Bibliothek ist eine direkte Übersetzung von C nach
XS (z. B. erstellt durch „h2xs -x“) ist oft ausreichend. Allerdings manchmal die Schnittstelle
sieht sehr C-ähnlich und gelegentlich nicht intuitiv aus, insbesondere wenn die C-Funktion funktioniert
ändert einen seiner Parameter oder gibt einen Inband-Fehler zurück (wie in „negative Rückgabewerte“)
bedeuten Fehler"). In Fällen, in denen der Programmierer eine Perl-ähnlichere Schnittstelle erstellen möchte
Die folgende Strategie kann dabei helfen, die kritischeren Teile der Schnittstelle zu identifizieren.
Identifizieren Sie die C-Funktionen mit Ein-/Ausgabe- oder Ausgabeparametern. Die XSUBs dafür
Funktionen können möglicherweise Listen an Perl zurückgeben.
Identifizieren Sie die C-Funktionen, die einige Inband-Informationen als Hinweis auf einen Fehler verwenden. Sie dürfen
Kandidaten sein, die im Fehlerfall undef oder eine leere Liste zurückgeben. Wenn der Fehler sein kann
Wenn ein Fehler ohne Aufruf der C-Funktion erkannt wird, können Sie zur Meldung einen INIT:-Abschnitt verwenden
der Fehlschlag. Für Fehler, die nach der Rückkehr der C-Funktion erkennbar sind, empfiehlt sich möglicherweise die Verwendung von a
POSTCALL: Abschnitt zur Bearbeitung des Fehlers. In komplizierteren Fällen verwenden Sie CODE: oder PPCODE:
.
Wenn viele Funktionen basierend auf dem Rückgabewert dieselbe Fehleranzeige verwenden, möchten Sie möglicherweise
um eine spezielle Typdefinition zu erstellen, um diese Situation zu bewältigen. Setzen
typedef int negative_is_failure;
am Anfang der XS-Datei und erstellen Sie einen OUTPUT-Typemap-Eintrag für
„negative_is_failure“, das negative Werte in „undef“ umwandelt, oder vielleicht Krächzen()S. Nach
Dadurch wird der Rückgabewert vom Typ „negative_is_failure“ eine Perl-ähnlichere Schnittstelle erstellen.
Identifizieren Sie, welche Werte nur von den C- und XSUB-Funktionen selbst verwendet werden, beispielsweise wenn a
Der Parameter einer Funktion sollte der Inhalt einer globalen Variablen sein. Wenn Perl nicht benötigt
Um auf den Inhalt des Werts zuzugreifen, ist es möglicherweise nicht erforderlich, eine Übersetzung bereitzustellen
für diesen Wert von C nach Perl.
Identifizieren Sie die Zeiger in den C-Funktionsparameterlisten und Rückgabewerten. Einige Hinweise
können zur Implementierung von Ein-/Ausgabe- oder Ausgabeparametern verwendet werden, sie können in XS mit verarbeitet werden
den unären Operator „&“ und möglicherweise die Verwendung des Schlüsselworts NO_INIT. Einige andere werden es tun
erfordern die Handhabung von Typen wie „int *“, und man muss entscheiden, was für ein nützliches Perl ist
In einem solchen Fall genügt eine Übersetzung. Wenn die Semantik klar ist, ist es ratsam, sie zu setzen
die Übersetzung in eine Typemap-Datei.
Identifizieren Sie die von den C-Funktionen verwendeten Strukturen. In vielen Fällen kann die Verwendung hilfreich sein
die T_PTROBJ-Typemap für diese Strukturen, damit sie wie gewünscht von Perl manipuliert werden können
Objekte. (Dies wird automatisch von „h2xs -x“ erledigt.)
Wenn derselbe C-Typ in mehreren verschiedenen Kontexten verwendet wird, die unterschiedliche Anforderungen erfordern
Übersetzungen, „typedef“ ordnet mehrere neue Typen diesem C-Typ zu und erstellt separate
Typkarte Einträge für diese neuen Typen. Verwenden Sie diese Typen in Deklarationen des Rückgabetyps und
Parameter zu XSUBs.
Perl Objekte Und C Strukturen
Beim Umgang mit C-Strukturen sollte man eine der beiden Optionen wählen T_PTROBJ or T_PTRREF für den XS
Typ. Beide Typen sind für die Verarbeitung von Zeigern auf komplexe Objekte konzipiert. Der T_PTRREF-Typ
ermöglicht, dass das Perl-Objekt nicht gesegnet wird, während der Typ T_PTROBJ erfordert, dass das
Objekt sei gesegnet. Durch die Verwendung von T_PTROBJ kann eine Form der Typprüfung erreicht werden, da die
XSUB versucht zu überprüfen, ob das Perl-Objekt den erwarteten Typ hat.
Der folgende XS-Code zeigt die getnetconfigent() Funktion, die mit ONC+ TIRPC verwendet wird.
Die getnetconfigent() Die Funktion gibt einen Zeiger auf eine C-Struktur zurück und verfügt über das C
Prototyp unten gezeigt. Das Beispiel zeigt, wie der C-Zeiger zu einem Perl-Zeiger wird
Referenz. Perl betrachtet diese Referenz als einen Hinweis auf ein gesegnetes Objekt und wird es tun
Versuchen Sie, einen Destruktor für das Objekt aufzurufen. Im XS wird ein Destruktor bereitgestellt
Quelle, um den von verwendeten Speicher freizugeben getnetconfigent(). Destruktoren in XS können erstellt werden von
Angabe einer XSUB-Funktion, deren Name mit dem Wort endet DESTROY. XS-Destruktoren können sein
Wird verwendet, um Speicher freizugeben, der möglicherweise von einem anderen XSUB mallociert wurde.
struct netconfig *getnetconfigent(const char *netid);
Für „struct netconfig“ wird eine „typedef“ erstellt. Das Perl-Objekt wird in a gesegnet
Klasse, die mit dem Namen des C-Typs übereinstimmt, mit angehängtem Tag „Ptr“, und der Name sollte
keine eingebetteten Leerzeichen enthalten, wenn es sich um einen Perl-Paketnamen handelt. Der Destruktor wird platziert
in einer Klasse, die der Klasse des Objekts entspricht, und das Schlüsselwort PREFIX wird dazu verwendet
Kürzen Sie den Namen auf das Wort DESTROY, wie Perl es erwartet.
typedef struct netconfig Netconfig;
MODUL = RPC PAKET = RPC
Netconfig *
getnetconfigent(netid)
char *netid
MODUL = RPC PAKET = NetconfigPtr PREFIX = rpcb_
ungültig
rpcb_DESTROY(netconf)
Netconfig *netconf
CODE:
printf("Jetzt in NetconfigPtr::DESTROY\n");
free( netconf );
Für dieses Beispiel ist der folgende Typemap-Eintrag erforderlich. Weitere Informationen finden Sie unter perlxstypemap
Informationen zum Hinzufügen neuer Typemaps für eine Erweiterung.
TYPMAP
Netconfig * T_PTROBJ
Dieses Beispiel wird mit den folgenden Perl-Anweisungen verwendet.
RPC verwenden;
$netconf = getnetconfigent("udp");
Wenn Perl das von $netconf referenzierte Objekt zerstört, sendet es das Objekt an
mitgelieferte XSUB DESTROY-Funktion. Perl kann dies nicht feststellen und kümmert sich auch nicht darum
Das Objekt ist eine C-Struktur und kein Perl-Objekt. In diesem Sinne gibt es keinen Unterschied zwischen
das von der erstellte Objekt getnetconfigent() XSUB und ein von einem normalen Perl erstelltes Objekt
Subroutine.
Sicher Speicherung Statisch Daten-Management in XS
Ab Perl 5.8 wurde ein Makro-Framework definiert, um statische Daten zu ermöglichen
Sicher in XS-Modulen gespeichert, auf die von einem Multithread-Perl aus zugegriffen werden kann.
Obwohl die Makros in erster Linie für die Verwendung mit Multithread-Perl konzipiert sind, sind sie es auch
so konzipiert, dass sie auch mit Perl ohne Thread funktionieren.
Es wird daher dringend empfohlen, diese Makros von allen XS-Modulen zu verwenden, die Folgendes erstellen
Verwendung statischer Daten.
Der einfachste Weg, einen Vorlagensatz von Makros zur Verwendung zu erhalten, ist die Angabe von „-g“.
("--global") Option mit h2xs (siehe h2xs).
Nachfolgend finden Sie ein Beispielmodul, das die Makros nutzt.
#define PERL_NO_GET_CONTEXT
#include „EXTERN.h“
#include „perl.h“
#include „XSUB.h“
/* Globale Daten */
#define MY_CXT_KEY „BlindMice::_guts“ XS_VERSION
typedef-Struktur {
int zählen;
Char-Name[3][100];
} my_cxt_t;
START_MY_CXT
MODUL = BlindMice PAKET = BlindMice
STIEFEL:
{
MY_CXT_INIT;
MY_CXT.count = 0;
strcpy(MY_CXT.name[0], "None");
strcpy(MY_CXT.name[1], "None");
strcpy(MY_CXT.name[2], "None");
}
int
newMouse(char * name)
VOREINIT:
dMY_CXT;
CODE:
if (MY_CXT.count >= 3) {
warn("Habe bereits 3 blinde Mäuse");
RETVAL = 0;
}
else {
RETVAL = ++ MY_CXT.count;
strcpy(MY_CXT.name[MY_CXT.count - 1], name);
}
AUSGABE:
WIEDERHOLUNG
Zeichen *
get_mouse_name(index)
int-Index
VOREINIT:
dMY_CXT;
CODE:
if (index > MY_CXT.count)
croak("Es gibt nur 3 blinde Mäuse.");
sonst
RETVAL = MY_CXT.name[index - 1];
AUSGABE:
WIEDERHOLUNG
ungültig
KLON(...)
CODE:
MY_CXT_CLONE;
MY_CXT REFERENCE
MY_CXT_KEY
Dieses Makro wird verwendet, um einen eindeutigen Schlüssel zu definieren, der auf die statischen Daten für ein XS verweist
Modul. Das vorgeschlagene Benennungsschema, wie es von h2xs verwendet wird, besteht darin, eine Zeichenfolge zu verwenden
besteht aus dem Modulnamen, der Zeichenfolge „::_guts“ und der Modulversionsnummer.
#define MY_CXT_KEY "MyModule::_guts" XS_VERSION
typedef my_cxt_t
Diese Strukturtypdefinition sollen immer „my_cxt_t“ heißen. Die anderen „CXT*“-Makros gehen davon aus
die Existenz des Typedef-Namens „my_cxt_t“.
Deklarieren Sie eine Typdefinition mit dem Namen „my_cxt_t“, die eine Struktur ist, die alle Daten enthält
Das muss interpreterlokal sein.
typedef-Struktur {
int some_value;
} my_cxt_t;
START_MY_CXT
Platzieren Sie das Makro START_MY_CXT immer direkt nach der Deklaration von „my_cxt_t“.
MY_CXT_INIT
Das Makro MY_CXT_INIT initialisiert den Speicher für die Struktur „my_cxt_t“.
It sollen genau einmal aufgerufen werden, normalerweise in einem BOOT:-Abschnitt. Wenn Sie pflegen
Bei mehreren Interpretern sollte es in jeder Interpreterinstanz einmal aufgerufen werden, außer
für Dolmetscher, die von vorhandenen geklont wurden. (Aber siehe „MY_CXT_CLONE“ unten.)
dMY_CXT
Verwenden Sie das dMY_CXT-Makro (eine Deklaration) in allen Funktionen, die auf MY_CXT zugreifen.
MY_CXT
Verwenden Sie das Makro MY_CXT, um auf Mitglieder der Struktur „my_cxt_t“ zuzugreifen. Zum Beispiel, wenn
„my_cxt_t“ ist
typedef-Struktur {
int index;
} my_cxt_t;
Verwenden Sie dies dann, um auf das Mitglied „index“ zuzugreifen
dMY_CXT;
MY_CXT.index = 2;
aMY_CXT/pMY_CXT
Die Berechnung von „dMY_CXT“ kann recht aufwändig sein und den Aufwand für den Aufruf vermeiden
In jeder Funktion ist es möglich, die Deklaration an andere Funktionen weiterzugeben
die Makros „aMY_CXT“/„pMY_CXT“, z
void sub1() {
dMY_CXT;
MY_CXT.index = 1;
sub2(aMY_CXT);
}
void sub2(pMY_CXT) {
MY_CXT.index = 2;
}
Analog zu „pTHX“ gibt es äquivalente Formen dafür, wenn das Makro das erste oder ist
zuletzt in mehreren Argumenten, wobei ein Unterstrich ein Komma darstellt, z. B. „_aMY_CXT“,
„aMY_CXT_“, „_pMY_CXT“ und „pMY_CXT_“.
MY_CXT_CLONE
Wenn ein neuer Interpreter standardmäßig als Kopie eines vorhandenen erstellt wird (z. B. via
„threads->create()“) verwenden beide Interpreter dieselbe physische my_cxt_t-Struktur.
Der Aufruf von „MY_CXT_CLONE“ (normalerweise über die Funktion „CLONE()“ des Pakets) führt zu a
Byte-für-Byte-Kopie der Struktur, die erstellt werden soll, und jedes zukünftige dMY_CXT verursacht
stattdessen die Kopie, auf die zugegriffen werden soll.
MY_CXT_INIT_INTERP(meine_perl)
dMY_CXT_INTERP(meine_perl)
Dies sind Versionen der Makros, die einen expliziten Interpreter als Argument verwenden.
Beachten Sie, dass diese Makros nur innerhalb von zusammenarbeiten gleich Quelldatei; das ist ein
dMY_CTX in einer Quelldatei greift auf eine andere Struktur zu als ein dMY_CTX in einer anderen
Quelldatei.
Thread-bewusst System Schnittstellen
Ab Perl 5.8 weiß Perl auf C/C++-Ebene, wie System-/Bibliotheksschnittstellen umschlossen werden
die Thread-fähige Versionen haben (z. B getpwent_r()) in Frontend-Makros (z. B getpwent())
die die Multithread-Interaktion mit dem Perl-Interpreter korrekt verarbeiten. Dieser Wille
Da dies transparent geschieht, müssen Sie lediglich einen Perl-Interpreter instanziieren.
Dieser Umbruch erfolgt immer beim Kompilieren der Perl-Kernquelle (PERL_CORE ist definiert) oder der
Perl-Kernerweiterungen (PERL_EXT ist definiert). Beim Kompilieren von XS-Code außerhalb des Perl-Kerns
die Umhüllung findet nicht statt. Beachten Sie jedoch, dass die Vermischung der _r-Formen (wie Perl
kompiliert für den Multithread-Betrieb reicht aus) und die _r-losen Formen sind weder gut noch
definiert (inkonsistente Ergebnisse, Datenbeschädigung oder sogar Abstürze werden wahrscheinlicher), noch
Ist es sehr tragbar?
Beispiele:
Datei „RPC.xs“: Schnittstelle zu einigen ONC+ RPC-Bind-Bibliotheksfunktionen.
#define PERL_NO_GET_CONTEXT
#include „EXTERN.h“
#include „perl.h“
#include „XSUB.h“
#enthalten
typedef struct netconfig Netconfig;
MODUL = RPC PAKET = RPC
SV *
rpcb_gettime(host="localhost")
char *host
VOREINIT:
time_t timep;
CODE:
ST(0) = sv_newmortal();
if( rpcb_gettime( host, &timep ) )
sv_setnv( ST(0), (double)timep );
Netconfig *
getnetconfigent(netid="udp")
char *netid
MODUL = RPC PAKET = NetconfigPtr PREFIX = rpcb_
ungültig
rpcb_DESTROY(netconf)
Netconfig *netconf
CODE:
printf("NetconfigPtr::DESTROY\n");
free( netconf );
Datei „typemap“: Benutzerdefinierte Typemap für RPC.xs. (vgl. perlxstypemap)
TYPMAP
Netconfig * T_PTROBJ
Datei „RPC.pm“: Perl-Modul für die RPC-Erweiterung.
Paket RPC;
Exporteur erforderlich;
erfordern DynaLoader;
@ISA = qw(Exporter DynaLoader);
@EXPORT = qw(rpcb_gettime getnetconfigent);
Bootstrap-RPC;
1;
Datei „rpctest.pl“: Perl-Testprogramm für die RPC-Erweiterung.
RPC verwenden;
$netconf = getnetconfigent();
$a = rpcb_gettime();
print „time = $a\n“;
print "netconf = $netconf\n";
$netconf = getnetconfigent("tcp");
$a = rpcb_gettime("Pappel");
print „time = $a\n“;
print "netconf = $netconf\n";
VORSICHTEN
XS-Code hat vollen Zugriff auf Systemaufrufe, einschließlich C-Bibliotheksfunktionen. Es hat somit die
Fähigkeit, Dinge zu stören, die der Perl-Kern oder andere Module eingerichtet haben,
wie Signalhandler oder Dateihandles. Es könnte den Speicher beeinträchtigen oder eine beliebige Anzahl davon
schädliche Dinge. Nicht.
Einige Module verfügen über eine Ereignisschleife, die auf Benutzereingaben wartet. Es ist höchst unwahrscheinlich, dass zwei
Solche Module würden in einer einzigen Perl-Anwendung angemessen zusammenarbeiten.
Im Allgemeinen betrachtet sich der Perl-Interpreter als das Zentrum des Universums
Perl-Programm geht. XS-Code wird als Helfer betrachtet, um Dinge zu erreichen, die Spaß machen
funktioniert nicht oder nicht schnell genug, ist aber immer Perl unterworfen. Der nähere XS-Code
Je mehr Sie sich an dieses Modell halten, desto unwahrscheinlicher ist es, dass es zu Konflikten kommt.
Ein Bereich, in dem es Konflikte gab, betrifft C-Locales. (Siehe Perllocale.)
Mit einer Ausnahme und sofern nicht anders angegeben, richtet Perl das zugrunde liegende Gebietsschema ein
Das Programm wird in dem von der Umgebung übergebenen Gebietsschema ausgeführt. Das ist ein
wichtiger Unterschied zu einem generischen C-Sprachprogramm, bei dem das zugrunde liegende Gebietsschema das ist
„C“-Gebietsschema, es sei denn, das Programm ändert es. Ab Version 5.20 ist dieses zugrunde liegende Gebietsschema
vollständig vor reinem Perl-Code außerhalb des lexikalischen Bereichs von „use locale“ verborgen, mit Ausnahme von
ein paar Funktionsaufrufe im POSIX-Modul, die es notwendigerweise verwenden. Aber die
zugrunde liegendes Gebietsschema, mit einer Ausnahme, die XS-Code ausgesetzt ist, was sich auf die gesamte C-Bibliothek auswirkt
Routinen, deren Verhalten vom Gebietsschema abhängt. Ihr XS-Code sollte besser nicht davon ausgehen, dass die
Das zugrunde liegende Gebietsschema ist „C“. Die Ausnahme bildet die Gebietsschemakategorie „LC_NUMERIC“.
Der Grund dafür, dass es sich um eine Ausnahme handelt, liegt darin, dass die Erfahrung gezeigt hat, dass es für XS problematisch sein kann
Code, wohingegen wir keine Berichte über Probleme mit den anderen Gebietsschemakategorien erhalten haben. Und
Der Grund dafür, dass diese eine Kategorie problematisch ist, liegt darin, dass das Zeichen als Dezimalzahl verwendet wird
Der Punkt kann variieren. In vielen europäischen Sprachen wird ein Komma verwendet, im Gegensatz zu Englisch und damit auch Perl
Erwarte einen Punkt (U+002E: FULL STOP). Viele Module können nur das Basiszeichen verarbeiten
ein Punkt sein, und so versucht Perl, es so zu machen. Bis Perl v5.20 war der Versuch
lediglich um „LC_NUMERIC“ beim Start auf das Gebietsschema „C“ zu setzen. Beliebig setlocale() Andernfalls
würde es ändern; Dies führte zu einigen Fehlern. Daher versucht Perl ab Version 5.22, dies zu tun
Lassen Sie „LC_NUMERIC“ für XS-Code immer auf „C“ eingestellt.
Zusammenfassend erfahren Sie hier, was Sie erwartet und wie mit Gebietsschemata im XS-Code umgegangen wird:
Nicht gebietsschemabezogener XS-Code
Bedenken Sie, dass Ihr Code, selbst wenn Sie glauben, dass er das Gebietsschema nicht berücksichtigt, möglicherweise ein C aufruft
Bibliotheksfunktion also. Hoffentlich wird die Manpage für eine solche Funktion darauf hinweisen
diese Abhängigkeit, aber die Dokumentation ist unvollständig.
Das aktuelle Gebietsschema wird XS-Code ausgesetzt, mit Ausnahme möglicherweise von „LC_NUMERIC“ (erklärt in
den nächsten Absatz). Es liegen keine Berichte über Probleme mit dem anderen vor
Kategorien. Perl initialisiert die Dinge beim Start so, dass das aktuelle Gebietsschema dasjenige ist
Dies wird durch die zu diesem Zeitpunkt gültige Umgebung des Benutzers angezeigt. Sehen
„UMWELT“ in Perllocale.
Allerdings hat Perl bis Version 5.20 die Dinge beim Start so initialisiert, dass „LC_NUMERIC“
wurde auf das Gebietsschema „C“ eingestellt. Aber wenn irgendein Code es irgendwo ändern würde, würde es bleiben
geändert. Das bedeutet, dass Ihr Modul nicht darauf zählen kann, dass „LC_NUMERIC“ etwas enthält
Insbesondere können Sie davon keine Gleitkommazahlen (einschließlich Versionszeichenfolgen) erwarten
haben Punkte darin. Wenn Sie keinen Nicht-Punkt zulassen, könnte Ihr Code beschädigt werden
irgendwo hat sich das Gebietsschema geändert. Aus diesem Grund hat v5.22 das Verhalten so geändert, dass Perl
versucht, „LC_NUMERIC“ im Gebietsschema „C“ beizubehalten, mit Ausnahme der internen Operationen
wo es etwas anderes sein sollte. XS-Code, der sich schlecht verhält, kann sich jederzeit ändern
das Gebietsschema sowieso, aber die häufigste Instanz davon wird überprüft und behandelt.
Gebietsschemabezogener XS-Code
Wenn das Gebietsschema aus der Umgebung des Benutzers gewünscht wird, sollte XS nicht erforderlich sein
Code zum Festlegen des Gebietsschemas mit Ausnahme von „LC_NUMERIC“, da Perl es bereits eingerichtet hat. XS
Code sollte eine Änderung des Gebietsschemas vermeiden, da sich dies nachteilig auf andere, nicht verwandte,
Code und ist möglicherweise nicht threadsicher. Einige außerirdische Bibliotheken, die möglicherweise aufgerufen werden, tun dies jedoch
Legen Sie es fest, z. B. „Gtk“. Dies kann zu Problemen für den Perl-Kern und andere Module führen.
Ab Version 5.20.1 wird die Funktion aufgerufen sync_locale() ab XS sollte ausreichen
um die meisten dieser Probleme zu vermeiden. Zuvor benötigen Sie eine reine Perl-Anweisung
macht dies:
POSIX::setlocale(LC_ALL, POSIX::setlocale(LC_ALL));
Für den Fall, dass Ihr XS-Code möglicherweise das zugrunde liegende Gebietsschema „LC_NUMERIC“ benötigt, gibt es eines
Für den Zugriff stehen Makros zur Verfügung. siehe „Gebietsschemabezogene Funktionen und Makros“ in Perlapi.
XS VERSION
Dieses Dokument behandelt Funktionen, die von „ExtUtils::ParseXS“ (auch bekannt als „xsubpp“) unterstützt werden.
3.13_01.
Nutzen Sie Perlxs online über die Dienste von onworks.net