Read-only Variablen in XS
Im Zusammenhang mit meinem MMapDB Modul wollte ich den Speicherbedarf optimieren und dachte, es müsse doch möglich sein, auf einen String, den man auf C-Level in einem read-only Speichersegment hat, in Perl zuzugreifen, ohne ihn zu kopieren.
Normalerweise würde man in XS einen Perl-String folgendermaßen erzeugen:
sv=newSVpv(pointer, length)
Dabei wird allerdings Speicher alloziiert und der String kopiert. Das wollte ich vermeiden.
Nun gibt es im Perl API die Macros SvPV_set, SvLEN_set und SvCUR_set, mit
denen man den Pointer, die alloziierte Länge und die aktuelle Länge eines Perl-Strings setzen kann. Da mein String jedoch
nicht von Perl alloziiert wurde, mußte ich irgendwie verhindern, daß Perl versucht den String freizugeben, wenn die Variable
vom Garbage Collector vernichtet wird. Der Aufruf von Safefree() mußte also verhindert werden.
Das Studium des Perl-Source-Codes ergab, daß eine alloziierte Länge von Null den Safefree-Aufruf verhindert. Der Trick
ist also SvLEN_set(sv, 0). Am Ende sah meine Lösung so aus:
sv=newSV(0);
SvUPGRADE(sv, SVt_PV);
SvPOK_only(sv);
SvPV_set(sv, pointer);
SvLEN_set(sv, 0);
SvCUR_set(sv, length);
SvREADONLY_on(sv);
Das lies ich mir von den Machern von Perl auf der perl5-porters Mailing Liste bestätigen. Es wurde auch
bestätigt, daß das mit großer Wahrscheinlichkeit auch in zukünftigen Perl-Versionen so bleiben wird.
Letzte Aktualisierung: 12.07.2009

