Dies ist der Befehl PDL::Internalsp, 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
PDL::Internals – Beschreibung einiger Aspekte der aktuellen Interna
BESCHREIBUNG
Einleitung / Intro
In diesem Dokument werden verschiedene Aspekte der aktuellen Implementierung von PDL erläutert. Wenn Sie nur
Wenn Sie PDL für etwas verwenden möchten, müssen Sie dies auf keinen Fall lesen. Auch wenn du willst
Um Ihre C-Routinen mit PDL zu verbinden oder neue PDL::PP-Funktionen zu erstellen, ist dies nicht erforderlich
Lesen Sie diese Manpage (obwohl sie möglicherweise informativ ist). Dieses Dokument richtet sich in erster Linie an
Personen, die daran interessiert sind, die Interna von PDL zu debuggen oder zu ändern. Das zu lesen ist gut
Verständnis der C-Sprache sowie der Programmierung und Datenstrukturen im Allgemeinen ist
erforderlich, sowie einige Perl-Kenntnisse. Wenn Sie dieses Dokument durchlesen und
Sie verstehen alles und können angeben, worauf sich ein Teil dieses Dokuments bezieht
PDL-Kernquellen und zusätzlich Schwierigkeiten, PDL::PP zu verstehen, werden Sie mit dem ausgezeichnet
Titel „PDL Guru“ (natürlich ist die aktuelle Version dieses Dokuments so unvollständig, dass
dies ist aufgrund dieser Notizen nahezu unmöglich).
Warnung: Wenn Sie den Eindruck haben, dass dieses Dokument veraltet ist, informieren Sie bitte die PDL
E-Mail-Liste der Träger ([E-Mail geschützt] ). Das kann durchaus passieren.
Pfeifen
Das PDL-Datenobjekt ist im Allgemeinen eine undurchsichtige Skalarreferenz in einer PDL-Struktur in
Speicher. Alternativ kann es sich um eine Hash-Referenz mit dem Feld „PDL“ handeln, das Folgendes enthält
Skalarreferenz (dies erleichtert das Überladen von Piddles, siehe PDL::Objects). Das können Sie ganz einfach
Finden Sie auf der Perl-Ebene heraus, mit welcher Art von Rätsel Sie es zu tun haben. Der Beispielcode
Im Folgenden wird gezeigt, wie es geht:
#Überprüfen Sie, ob das ein Rätsel ist
sterben „kein Piddle“, es sei denn UNIVERSAL::isa($pdl, 'PDL');
# Handelt es sich um eine Skalarreferenz oder eine Hashreferenz?
if (UNIVERSAL::isa($pdl, "HASH")) {
die „keine gültige PDL“, es sei denn, sie existiert $pdl->{PDL} &&
UNIVERSAL::isa($pdl->{PDL},'PDL');
print „Dies ist eine Hash-Referenz“,
„Das PDL-Feld enthält die Skalarreferenz\n“;
} Else {
print „Dies ist eine Skalarreferenz, die auf die Adresse $$pdl im Speicher zeigt\n“;
}
Die skalare Referenz zeigt auf die numerische Adresse einer C-Struktur vom Typ „pdl“, also
definiert in pdl.h. Die Zuordnung zwischen dem Objekt auf der Perl-Ebene und der C-Struktur
Die eigentlichen Daten und die Struktur, aus denen ein Piddle besteht, werden von der PDL enthalten
Typkarte. Die in der PDL-Typemap verwendeten Funktionen werden ziemlich oben definiert
Datei pdlcore.h. Wie sieht also die Struktur aus:
struct pdl {
unsigniertes langes Magicno; /* Speichert PDL_MAGICNO immer als Plausibilitätsprüfung */
/* Dies ist der erste, damit die meisten Zeigerzugriffe auf den falschen Typ abgefangen werden */
int-Zustand; /* Was ist in diesem PDL enthalten */
pdl_trans *trans; /* Undurchsichtiger Zeiger auf Interna der Transformation von
Elternteil */
pdl_vaffine *vafftrans;
void* sv; /* (optional) Zeiger zurück zum ursprünglichen SV.
Überprüfen Sie vor der Verwendung IMMER, ob der Wert ungleich Null ist.
Hierauf können wir uns nicht einigen, sonst würden wir es tun
werde niemals zerstört */
void *datasv; /* Zeiger auf SV, der Daten enthält. Refcnt erhöht */
void *data; /* Null: Für diesen sind keine Daten reserviert */
PDL_Indx nvals; /* Wie viele Werte zugewiesen */
int-Datentyp;
PDL_Indx *dims; /* Array von Datendimensionen */
PDL_Indx *dimincs; /* Array von Datenstandardinkrementen */
kurze ndims; /* Anzahl der Datendimensionen */
unsigned char *threadids; /* Startindex des Thread-Indexsatzes n */
unsigned char nthreadids;
pdl *Vorläufer; /* Ich gehöre zu einer mutierten Familie. make_physical_now muss
Kopiere mich in die neue Generation. */
pdl *future_me; /* Ich bin der „Damals“-PDL und das ist mein „Jetzt“ (oder moderner).
Version jedenfalls */
pdl_children Kinder;
kurzes Leben für; /* Perl-Seite nicht referenziert; lösche mich, wenn */
PDL_Indx def_dims[PDL_NDIMS]; /* Vorab zugewiesener Speicherplatz für Effizienz */
PDL_Indx def_dimincs[PDL_NDIMS]; /* Vorab zugewiesener Speicherplatz für Effizienz */
unsigned char def_threadids[PDL_NTHREADIDS];
struct pdl_magic *magic;
void *hdrsv; /* „Header“, von außen einstellbar */
};
Dies ist eine ziemliche Struktur zum Speichern einiger Daten. Was ist los?
Datenspeicher
Wir beginnen mit einigen der einfacheren Mitglieder: Da ist zunächst das
Mitglied
void *datasv;
was eigentlich ein Zeiger auf eine Perl-SV-Struktur („SV *“) ist. Der SV wird es voraussichtlich sein
stellt einen String dar, in dem die Daten des Piddles dicht gepackt gespeichert sind
form. Dieser Zeiger gilt als Referenz auf den SV, daher wurde der Referenzzähler gezählt
inkrementiert, als der „SV *“ hier platziert wurde (dieser Referenzzähler muss das Unternehmen tun).
mit dem Garbage-Collection-Mechanismus von Perl – machen Sie sich keine Sorgen, wenn das nicht viel bedeutet
Du). Dieser Zeiger darf den Wert „NULL“ haben, was bedeutet, dass es keinen gibt
tatsächlicher Perl-SV für diese Daten – die Daten könnten beispielsweise durch eine „mmap“ zugewiesen werden.
Betrieb. Beachten Sie, dass die Verwendung eines SV* lediglich der Zweckmäßigkeit dient und eine einfache Handhabung ermöglicht
Umwandlung gepackter Daten aus Dateien in Piddles. Bei anderen Implementierungen ist dies nicht der Fall
ausgeschlossen.
Der eigentliche Zeiger auf Daten wird im Member gespeichert
Leere *Daten;
welches einen Zeiger auf einen Speicherbereich mit Platz für enthält
PDL_Indx nvals;
Datenelemente des Datentyps dieses Piddles. PDL_Indx ist entweder „long“ oder „long long“
abhängig davon, ob Ihr Perl 64bit ist oder nicht.
Der Datentyp der Daten wird in der Variablen gespeichert
int-Datentyp;
Die Werte für dieses Mitglied sind im Enum „pdl_datatypes“ angegeben (siehe pdl.h).
Derzeit gibt es die Typen Byte, Short, Unsigned Short, Long, Float und Double, siehe auch
PDL::Types.
ABMESSUNGEN
Die Anzahl der Dimensionen im Piddle wird vom Mitglied vorgegeben
int ndims;
was zeigt, wie viele Einträge es in den Arrays gibt
PDL_Indx *dims;
PDL_Indx *dimincs;
Diese Arrays sind eng miteinander verbunden: „dims“ gibt die Größe der Dimensionen und an
„dimincs“ wird immer vom Code berechnet
PDL_Indx inc = 1;
for(i=0; i ndims; i++) {
it->dimincs[i] = inc; inc *= it->dims[i];
}
in der Routine „pdl_resize_defaultincs“ in „pdlapi.c“. Dies bedeutet, dass die
Dimincs können verwendet werden, um den Offset per Code zu berechnen
PDL_Indx offs = 0;
for(i=0; i ndims; i++) {
offs += it->dimincs[i] * index[i];
}
Dies ist jedoch nicht immer das Richtige, zumindest ohne dies sicher zu überprüfen
Dinge zuerst.
Standardspeicher
Da die allermeisten Piddles nicht mehr als 6 Dimensionen haben, sind es mehr
Es ist effizient, einen Standardspeicher für die Abmessungen und Abmessungen innerhalb der PDL zu haben
struk.
PDL_Indx def_dims[PDL_NDIMS];
PDL_Indx def_dimincs[PDL_NDIMS];
Die „dims“ und „dimincs“ können so eingestellt werden, dass sie auf den Anfang dieser Arrays zeigen, wenn
„ndims“ ist kleiner oder gleich der Kompilierzeitkonstante „PDL_NDIMS“. Das ist
Wichtig beim Freigeben einer Piddle-Struktur zu beachten. Dasselbe gilt auch für die Threadids:
unsigned char def_threadids[PDL_NTHREADIDS];
Magic
Es ist möglich, Rätsel mit Magie zu versehen, ähnlich wie Perls eigener Zaubermechanismus. Wenn
der Memberzeiger
struct pdl_magic *magic;
ungleich Null ist, ist mit der PDL etwas Magisches verbunden. Die Umsetzung von Magie kann sein
aus der Akte entnommen pdlmagic.c bei der Verteilung.
Staat
Eines der ersten Mitglieder der Struktur ist
int-Zustand;
Die möglichen Flags und ihre Bedeutung sind in „pdl.h“ angegeben. Diese sind hauptsächlich daran gewöhnt
Implementieren Sie den Lazy-Evaluation-Mechanismus und verfolgen Sie die darin enthaltenen Rätsel
Operationen.
Transformationen und virtuelle affine Transformationen
Wie Sie bereits wissen sollten, enthalten Rätsel oft Informationen darüber, woher sie kommen
aus. Zum Beispiel der Code
$b = $a->slice("2:5");
$b .= 1;
wird $a ändern. Also $b und $a kennt dass sie über a verbunden sind
„Slice“-Transformation. Diese Informationen werden in den Mitgliedern gespeichert
pdl_trans *trans;
pdl_vaffine *vafftrans;
Sowohl $a (die Elternteil) und $b (das Kind) speichern diese Informationen über die
Transformation in entsprechende Slots der „pdl“-Struktur.
„pdl_trans“ und „pdl_vaffine“ sind Strukturen, die wir uns genauer ansehen werden
unten mit.
Die Perl SVs
Wenn über Perl-SVs auf Piddles verwiesen wird, speichern wir einen zusätzlichen Verweis darauf
im Mitglied
void* sv;
um dem Benutzer eine Referenz zurückgeben zu können, wenn er das überprüfen möchte
Transformationsstruktur auf der Perl-Seite.
Außerdem lagern wir ein deckendes Mittel ein
void *hdrsv;
Dies dient lediglich dazu, dass der Benutzer beliebige Daten mit diesem SV verknüpfen kann. Dieses hier
wird im Allgemeinen durch sethdr- und gethdr-Aufrufe manipuliert.
Smart Referenzen und Transformationen: Aufschneiden und würfeln
Intelligente Referenzen und die meisten anderen grundlegenden Funktionen, die auf Piddles laufen, sind implementiert
Transformationen (Awie oben erwähnt), die durch den Typ „pdl_trans“ in dargestellt werden
PDL.
Eine Transformation verknüpft Eingabe- und Ausgabe-Piddles und enthält die gesamte Infrastruktur
definiert wie
· Ausgabe-Piddles werden aus Eingabe-Piddles erhalten
· Änderungen in intelligent verknüpften Ausgabe-Piddles (z. B. der der eines in Scheiben geschnittenen Elternteil pinkeln)
werden in Transformationen, in denen dies unterstützt wird (die
(am häufigsten verwendetes Beispiel ist hier „Slice“).
· Datentyp und Größe der zu erstellenden Ausgabe-Piddles werden ermittelt
Im Allgemeinen führt die Ausführung einer PDL-Funktion für eine Gruppe von Piddles zur Erstellung eines
Transformation des angeforderten Typs, die alle Eingabe- und Ausgabeargumente verknüpft (mindestens
diejenigen, die Rätsel sind). In PDL-Funktionen, die den Datenfluss zwischen Eingabe und Ausgabe unterstützen
args (z. B. „slice“, „index“) verlinkt diese Transformation Elternteil (Eingabe) und der (Ausgabe)
bleibt dauerhaft bestehen, bis entweder der Link explizit auf Benutzeranforderung unterbrochen wird („trennen“ bei).
der Perl-Ebene) oder alle Eltern und Kinder wurden zerstört. In diesen Fällen die
Die Transformation wird verzögert ausgewertet, z. B. nur ausgeführt, wenn die Piddle-Werte tatsächlich vorhanden sind
zugegriffen.
In nicht fließend Funktionen, zum Beispiel Addition („+“) und innere Produkte („inner“), die
Die Transformation wird genau wie in fließenden Funktionen installiert, aber dann ist die Transformation installiert
sofort ausgeführt und zerstört (Unterbrechung der Verknüpfung zwischen Eingabe- und Ausgabeargumenten)
bevor die Funktion zurückkehrt.
Es ist zu beachten, dass die enge Verbindung zwischen Eingabe- und Ausgabeargumenten einer fließenden Funktion besteht
(wie Slice) erfordert, dass auf diese Weise verknüpfte Piddle-Objekte am Leben gehalten werden
über den Punkt hinaus, an dem sie aus der Sicht von Perl den Rahmen verlassen haben:
$a = Nullen(20);
$b = $a->slice('2:4');
undef $a; # letzter Verweis auf $a ist jetzt zerstört
Obwohl $a nun gemäß Perls Regeln zerstört werden sollte, sollte das zugrunde liegende „pdl“
Struktur darf eigentlich nur dann freigegeben werden, wenn $b auch den Gültigkeitsbereich verlässt (da es immer noch ist).
verweist intern auf einige Daten von $a). Dieses Beispiel zeigt, dass ein solcher Datenfluss
Das Paradigma zwischen PDL-Objekten erfordert einen speziellen Zerstörungsalgorithmus, der das übernimmt
Verknüpfungen zwischen Rätseln berücksichtigen und die Lebensdauer dieser Objekte koppeln. Das Nicht-
Der triviale Algorithmus ist in der Funktion „pdl_destroy“ implementiert pdlapi.c. In der Tat die meisten
des Codes in pdlapi.c und pdlfamily.c geht es darum sicherzustellen, dass Piddles („pdl
*"s) werden je nach Interaktion mit zum richtigen Zeitpunkt erstellt, aktualisiert und freigegeben
andere Rätsel über PDL-Transformationen (denken Sie an „pdl_trans“).
Zugriff auf und Kindern und Eltern of a pinkeln
Wenn Rätsel dynamisch über Transformationen verknüpft werden, wie oben vorgeschlagen, geben Sie ein und
Ausgabepuddel werden als Eltern bzw. Kinder bezeichnet.
Ein Beispiel für die Verarbeitung der untergeordneten Elemente eines Piddles ist die Methode „baddata“ von
PDL::Bad (nur verfügbar, wenn Sie PDL mit der Option „WITH_BADVAL“ auf 1 kompiliert haben,
aber dennoch als Beispiel nützlich!).
Betrachten Sie die folgende Situation:
pdl> $a = rvals(7,7,Center=>[3,4]);
pdl> $b = $a->slice('2:4,3:5');
pdl> ? Vars
PDL-Variablen im Paket main::
Name Typ Dimension Flow State Mem
-------------------------------------------------- --------------
$a Double D [7,7] P 0.38Kb
$b Double D [3,3] VC 0.00 KB
Wenn ich nun plötzlich beschließe, dass $a als möglicherweise ungültige Werte enthaltend gekennzeichnet werden sollte,
mit automatisierten
pdl> $a->schlechte Daten(1)
dann möchte ich den Zustand von $b - es ist der - ebenfalls geändert werden (da es auch so sein wird).
Teilen oder erben Sie einige der Daten von $a und seien Sie es auch Dusche), so dass ich ein „B“ in der bekomme Staat
Feld:
pdl> ? Vars
PDL-Variablen im Paket main::
Name Typ Dimension Flow State Mem
-------------------------------------------------- --------------
$a Double D [7,7] PB 0.38 KB
$b Double D [3,3] VCB 0.00 KB
Dieses kleine Stück Magie wird von der Funktion „propogate_badflag“ ausgeführt, die unten aufgeführt ist:
/* newval = 1 bedeutet Flag setzen, 0 bedeutet es löschen */
/*Danke an Christian Soeller dafür */
void propogate_badflag( pdl *it, int newval ) {
PDL_DECL_CHILDLOOP(it)
PDL_START_CHILDLOOP(es)
{
pdl_trans *trans = PDL_CHILDLOOP_THISCHILD(it);
int i;
for( i = trans->vtable->nparents;
i < trans->vtable->npdls;
i++ ) {
pdl *child = trans->pdls[i];
if ( newval ) child->state |= PDL_BADVAL;
else child->state &= ~PDL_BADVAL;
/* Stellen Sie sicher, dass wir es an Enkel weitergeben, usw. */
propogate_badflag( child, newval );
} /* für: i */
}
PDL_END_CHILDLOOP(es)
} /* propogate_badflag */
Bei einem gegebenen Piddle („pdl *it“) durchläuft die Routine jede „pdl_trans“-Struktur, wobei
Der Zugriff auf diese Struktur erfolgt über das Makro „PDL_CHILDLOOP_THISCHILD“. Der und Kindern
des Piddles werden im Array „pdls“ gespeichert, nach dem Eltern, daher die Schleife von „i =
...nparents“ auf „i = ...nparents - 1“. Sobald wir den Zeiger auf das untergeordnete Piddle haben, können wir
kann damit machen, was wir wollen; Hier ändern wir den Wert der Variablen „state“, aber die
Details sind unwichtig). Was is Wichtig ist, dass wir hierzu „propogate_badflag“ aufrufen
piddle, um sicherzustellen, dass wir seine untergeordneten Elemente durchlaufen. Diese Rekursion stellt sicher, dass wir alle erreichen
Offspring eines bestimmten Rätsels.
Zugriff auf Eltern ist ähnlich, wobei die „for“-Schleife ersetzt wird durch:
for( i = 0;
i < trans->vtable->nparents;
i++ ) {
/* Dinge mit dem übergeordneten Element #i erledigen: trans->pdls[i] */
}
Was ist in a Transformation („pdl_trans“)
Alle Transformationen werden als Strukturen umgesetzt
struct XXX_trans {
int magicno; /* um Speicherüberschreibungen zu erkennen */
kurze Fahnen; /* Status der Übertragung */
pdl_transvtable *vtable; /* die alles wichtige vtable */
void (*freeproc)(struct pdl_trans *); /* Aufruf, um diese Übertragung freizugeben
(für den Fall, dass wir für diese Übersetzung ein paar Sachen mallocieren mussten) */
pdl *pdls[NP]; /* Die an der Transformation beteiligten PDLs */
int __datatype; /* der Typ der Transformation */
/* im Allgemeinen mehr Mitglieder
/* abhängig von der tatsächlichen Transformation (Slice, Add usw.)
*/
};
Die Transformation identifiziert alle an der Übertragung beteiligten „pdl“.
pdl *pdls[NP];
mit „NP“ abhängig von der Anzahl der Piddle-Args des jeweiligen Trans. Es zeichnet a auf
Zustand
kurze Fahnen;
und der Datentyp
int __datatype;
der trans (in die alle Piddles konvertiert werden müssen, sofern sie nicht explizit typisiert sind, PDL
Mit PDL::PP erstellte Funktionen stellen sicher, dass diese Konvertierungen nach Bedarf durchgeführt werden.
Am wichtigsten ist der Zeiger auf die vtable (virtuelle Tabelle), die die tatsächliche Datei enthält
Funktionalität
pdl_transvtable *vtable;
Die vtable-Struktur wiederum sieht etwa so aus (leicht vereinfacht von pdl.h für
Klarheit)
typedef struct pdl_transvtable {
pdl_transtype transtype;
int-Flags;
int nparents; /* Anzahl der übergeordneten PDLs (Eingabe) */
int npdls; /* Anzahl der untergeordneten PDLs (Ausgabe) */
char *per_pdl_flags; /* Optimierungsflags */
void (*redodims)(pdl_trans *tr); /* Finden Sie heraus, wie viele Kinder es haben */
void (*readdata)(pdl_trans *tr); /* Eltern zu Kindern fließen */
void (*writebackdata)(pdl_trans *tr); /* rückwärts fließen */
void (*freetrans)(pdl_trans *tr); /* Geben Sie sowohl den Inhalt als auch ihn frei
das Trans-Mitglied */
pdl_trans *(*copy)(pdl_trans *tr); /* Vollständige Kopie */
int structsize;
char *name; /* Meistens für Debugger */
} pdl_transvtable;
Wir konzentrieren uns auf die Callback-Funktionen:
void (*redodims)(pdl_trans *tr);
„redodims“ ermittelt die Abmessungen der zu erstellenden Piddles und wird aufgerufen
innerhalb der API-Funktion, die aufgerufen werden sollte, um sicherzustellen, dass die Dimensionen von a
Rätsel sind zugänglich (pdlapi.c):
void pdl_make_physdims(pdl *it)
„readdata“ und „writebackdata“ sind für die eigentlichen Berechnungen des Kindes verantwortlich
Daten der Eltern bzw. Elterndaten der Kinder (die
Datenflussaspekt). Der PDL-Kern stellt sicher, dass diese bei Bedarf aufgerufen werden, wenn piddle
auf Daten zugegriffen wird (Lazy-Evaluation). Die allgemeine API-Funktion stellt sicher, dass ein Piddle vorhanden ist
aktuell ist
void pdl_make_physvaffine(pdl *it)
Dies sollte vor dem Zugriff auf Piddle-Daten von XS/C aufgerufen werden (siehe Core.xs für einige
Beispiele).
„freetrans“ gibt nach Bedarf dynamisch zugewiesenen Speicher frei, der mit der Trans verknüpft ist
„kopieren“ kann die Transformation kopieren. Auch hier stellen mit PDL::PP erstellte Funktionen sicher
Das Kopieren und Freigeben über diese Rückrufe erfolgt zum richtigen Zeitpunkt. (Wenn sie es nicht tun
dass wir einen Speicherverlust haben – das ist in der Vergangenheit schon passiert ;).
Der Transformations- und Vtable-Code wird kaum von Hand geschrieben, sondern von generiert
PDL::PP aus prägnanten Beschreibungen.
Bestimmte Arten von Transformationen können sehr effizient optimiert werden, ohne dass dies erforderlich ist
explizite Methoden „readdata“ und „writebackdata“. Diese Transformationen werden aufgerufen
pdl_vaffine. Dazu gehören die meisten Dimensionsmanipulationsfunktionen (z. B. „slice“, „xchg“)
Klasse.
Der grundlegende Trick besteht darin, dass Eltern und Kind einer solchen Transformation auf die gleiche Weise arbeiten
(gemeinsam genutzter) Datenblock, den sie einfach anders interpretieren möchten (indem sie unterschiedliche verwenden).
„dims“, „dimincs“ und „offs“ für dieselben Daten, vergleiche die „pdl“-Struktur oben). Jede
Der Vorgang auf einem Piddle, der auf diese Weise Daten mit einem anderen teilt, erfolgt daher automatisch
vom Kind zum Elternteil und zurück geflogen – schließlich lesen und schreiben sie dasselbe
Speicherblock. Dies ist derzeit nicht Perl-Thread-sicher – kein großer Verlust seit der gesamten PDL
Der Kern ist nicht reentrant (Perl-Threading „!=" PDL-Threading!).
Unterschriften: einfädeln übrig elementar Geschäftstätigkeit
Die meisten dieser Funktionen des PDL-Threadings (automatische Iteration elementarer Operationen).
über Multi-Dim-Piddles) ist in der Datei implementiert pdlthread.c.
Die von PDL::PP generierten Funktionen (insbesondere die „readdata“ und „writebackdata“
Rückrufe) nutzen diese Infrastruktur, um sicherzustellen, dass die grundlegende Operation implementiert wird
durch die Trans wird in Übereinstimmung mit der Threading-Semantik von PDL durchgeführt.
Definieren neu PDL Funktionen -- Kleben Code Generation
Bitte beachten Sie PDL::PP und Beispiele in der PDL-Distribution. Implementierung und Syntax sind
Im Moment ist es noch lange nicht perfekt, aber es macht einen guten Job!
Die Core struct
Wie in PDL::API erläutert, verwendet PDL einen Zeiger auf eine Struktur, um PDL-Modulen den Zugriff zu ermöglichen
seine Kernroutinen. Die Definition dieser Struktur (der „Kern“-Struktur) finden Sie in pdlcore.h
(erstellt von pdlcore.h.PL in Basic/Core) und sieht ungefähr so aus
/* Struktur zum Speichern von Zeigern auf Kern-PDL-Routinen zur Verwendung durch
* viele Module
*/
Strukturkern {
I32-Version;
pdl* (*SvPDLV) ( SV* );
void (*SetSV_PDL) ( SV *sv, pdl *it );
#if definiert(PDL_clean_namespace) || definiert(PDL_OLD_API)
pdl* (*neu) ( ); /* Damit es mit Gimp-Perl funktioniert */
#else
pdl* (*pdlnew) ( ); /* umbenannt wegen C++-Konflikt */
#endif
pdl* (*tmp) ( );
pdl* (*create) (int type);
void (*destroy) (pdl *it);
...
}
typedef struct Core Core;
Das erste Feld der Struktur („Version“) wird verwendet, um die Konsistenz zwischen Modulen sicherzustellen
zur Laufzeit; Der folgende Code wird im BOOT-Abschnitt des generierten XS-Codes platziert:
if (PDL->Version != PDL_CORE_VERSION)
Perl_croak(aTHX_ „Foo muss mit der neu installierten PDL neu kompiliert werden“);
Wenn Sie ein neues Feld zum hinzufügen Core Struktur sollten Sie:
· Besprechen Sie es auf der E-Mail-Liste der PDL-Porter ([E-Mail geschützt] ) [mit dem
Möglichkeit, Ihre Änderungen an einem separaten Zweig des CVS-Baums vorzunehmen, wenn es sich um einen handelt
Änderung, deren Abschluss einige Zeit in Anspruch nehmen wird]
· Erhöhen Sie den Wert der Variablen $pdl_core_version in um 1 pdlcore.h.PL. Das setzt
der Wert des C-Makros „PDL_CORE_VERSION“, mit dem das Feld „Version“ gefüllt wird
· Dokumentation hinzufügen (z. B. zu PDL::API), wenn es sich um eine „nützliche“ Funktion für externe Module handelt
Autoren (und stellen außerdem sicher, dass der Code genauso gut dokumentiert ist wie der Rest von PDL ;)
Verwenden Sie PDL::Internalsp online über die Dienste von onworks.net