2015-06-10 10 views
6

Wie könnte ich SV-Wert von Null terminierte Zeichenfolge ohne Kopie erstellen? Wie newSVpv(const char*, STRLEN), aber ohne Kopie und mit Umzug in Perl (also muss Perl diesen Stringspeicher freigeben). Ich brauche das, um große Speicherzuweisungen und Kopien zu vermeiden.Perl SV-Wert von Zeiger ohne Kopie

fand ich folgendes Beispiel:

SV *r = sv_newmortal(); 
SvPOK_on(r); 
sv_usepvn_mg(r, string, strlen(string) + 1); 

Aber ich habe keine tiefe Kenntnis der XS-Interna und einige Zweifel haben.

Antwort

6

Wenn Sie möchten, dass Perl den Speicherblock verwaltet, muss er wissen, wie er ihn neu zuweisen und freigeben kann. Der einzige Speicher, den er neu zuordnen und freigeben kann, ist Speicher, der mit seinem Zuordner Newx zugewiesen wurde. (Andernfalls müsste jedem Speicherblock ein Reallocator zugewiesen werden.)

Wenn Sie den Speicherblock nicht mithilfe von Newx zuweisen können, besteht die beste Option möglicherweise darin, einen schreibgeschützten SV mit SvLEN zu erstellen bis Null. Das sagt Perl, dass es den Speicher nicht besitzt. Dieser SV könnte in eine Klasse gesegnet sein, die einen Destruktor hat, der den Speicher unter Verwendung der geeigneten Freigabe freigibt.

Wenn Sie den Speicherblock mit Newx zuordnen können, dann können Sie die folgenden Befehle verwenden:

SV* newSVpvn_steal_flags(pTHX_ const char* ptr, STRLEN len, const U32 flags) { 
#define newSVpvn_steal_flags(a,b,c) newSVpvn_steal_flags(aTHX_ a,b,c) 
    SV* sv; 

    assert(!(flags & ~(SVf_UTF8|SVs_TEMP|SV_HAS_TRAILING_NUL))); 

    sv = newSV(0); 
    sv_usepvn_flags(sv, ptr, len, flags & SV_HAS_TRAILING_NUL); 
    if ((flags & SVf_UTF8) && SvOK(sv)) { 
     SvUTF8_on(sv); 
    } 

    SvTAINT(sv); 

    if (flags & SVs_TEMP) { 
     sv_2mortal(sv); 
    } 

    return sv; 
} 

Hinweis: ptr sollte den Speicher verweisen, die von Newx zugewiesen wurde, und es muss zu Beginn des Punktes Block zurückgegeben von Newx.

Hinweis: Akzeptiert Flaggen SVf_UTF8 (angeben, dass ptr die UTF-8-Codierung der Zeichenfolge in Perl zu sehen ist), SVs_TEMP (zu sv_2mortal auf dem SV genannt hat) und SV_HAS_TRAILING_NUL (siehe unten).

Hinweis: Bei einigen Codes wird erwartet, dass der String-Puffer von Skalaren eine nachgestellte NUL aufweist (obwohl die Länge des Puffers bekannt ist und der Puffer NULs enthalten kann). Wenn der Speicherblock, den Sie zugewiesen haben, ein hinteres NUL hinter dem Ende der Daten aufweist (z. B. eine C-style NUL-terminierte Zeichenfolge), übergeben Sie das SV_HAS_TRAILING_NUL-Flag. Wenn nicht, wird die Funktion versuchen, den Puffer zu erweitern und eine NUL hinzuzufügen.

+1

magic kann auch verwendet werden, um einen benutzerdefinierten Deallocator über den Slot "svt_free" an den SV anzuschließen. – salva

Verwandte Themen