2015-06-10 6 views
6

Come è possibile creare il valore SV dalla stringa terminata null senza copia? Come newSVpv(const char*, STRLEN) ma senza copia e con spostamento della proprietà in Perl (quindi Perl deve rilasciare quella memoria di stringa). Ne ho bisogno per evitare un'enorme allocazione e copia della memoria.Perl Valore SV dal puntatore senza copia

ho trovato seguente esempio:

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

ma io non avere profonda conoscenza dei meccanismi interni XS e avere qualche dubbio.

risposta

6

Se si desidera che Perl gestisca il blocco di memoria, deve sapere come riallocarlo e deallocarlo. L'unica memoria che sa come riallocare e deallocare è la memoria allocata usando il suo allocatore, Newx. (Altrimenti, dovrebbe associare un reallocator e un deallocator a ciascun blocco di memoria.)

Se non è possibile allocare il blocco di memoria utilizzando Newx, l'opzione migliore potrebbe essere quella di creare un SV di sola lettura con il set SvLEN a zero. Questo dice a Perl che non possiede la memoria. Quella SV potrebbe essere benedetta in una classe che ha un distruttore che assegnerà la memoria usando l'appropriato deallocator.

Se è possibile allocare il blocco di memoria utilizzando Newx, quindi è possibile utilizzare il seguente:

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; 
} 

Nota: ptr dovrebbe puntare a memoria che è stata allocata da Newx, e deve indicare l'inizio del blocco restituito da Newx.

Nota: Accetta bandiere SVf_UTF8 (per specificare che ptr è la codifica UTF-8 della stringa di essere visto in Perl), SVs_TEMP (per avere sv_2mortal invitato la SV) e SV_HAS_TRAILING_NUL (vedi sotto).

Nota: alcuni codici prevedono che il buffer di stringa degli scalari abbia un NUL finale (anche se la lunghezza del buffer è nota e anche se il buffer può contenere NUL). Se il blocco di memoria che hai assegnato ha un NUL finale oltre la fine dei dati (ad esempio una stringa terminata NUL in stile C), quindi passa il flag SV_HAS_TRAILING_NUL. In caso contrario, la funzione tenterà di estendere il buffer e aggiungere un NUL.

+1

magic può anche essere utilizzato per collegare un deallocator personalizzato a SV, tramite lo slot 'svt_free'. – salva