2015-06-10 13 views
6

Làm cách nào tôi có thể tạo giá trị SV từ chuỗi bị hủy không có bản sao? Giống như newSVpv(const char*, STRLEN) nhưng không có bản sao và chuyển quyền sở hữu sang Perl (vì vậy Perl phải giải phóng bộ nhớ chuỗi đó). Tôi cần điều này để tránh phân bổ bộ nhớ lớn và sao chép.Giá trị SV Perl từ con trỏ mà không cần sao chép

tôi thấy ví dụ sau đây:

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

Nhưng tôi không có kiến ​​thức sâu sắc về internals XS và có một số nghi ngờ.

Trả lời

6

Nếu bạn muốn Perl quản lý khối bộ nhớ, nó cần phải biết cách phân bổ lại và xử lý nó. Bộ nhớ duy nhất nó biết làm thế nào để tái phân bổ và deallocate là bộ nhớ được phân bổ bằng cách sử dụng cấp phát của nó, Newx. (Nếu không, nó sẽ phải liên kết một bộ chia hồi âm và bộ cân đối với mỗi khối bộ nhớ.)

Nếu bạn không thể cấp phát khối bộ nhớ bằng cách sử dụng Newx, thì lựa chọn tốt nhất của bạn có thể là tạo SV chỉ đọc với SvLEN bộ không. Điều đó nói với Perl rằng nó không sở hữu bộ nhớ. Rằng SV có thể được ban phước vào một lớp có một destructor sẽ deallocate bộ nhớ bằng cách sử dụng deallocator thích hợp.

Nếu bạn có thể phân bổ các khối bộ nhớ sử dụng Newx, sau đó bạn có thể sử dụng như sau:

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

Lưu ý: ptr phải trỏ đến bộ nhớ đã được phân bổ bởi Newx, và nó phải trỏ đến khi bắt đầu khối được trả về bởi Newx.

Lưu ý: Chấp nhận cờ SVf_UTF8 (để xác định rằng ptr là bảng mã UTF-8 của chuỗi để được nhìn thấy trong Perl), SVs_TEMP (có sv_2mortal kêu gọi SV) và SV_HAS_TRAILING_NUL (xem dưới đây). Lưu ý: Một số mã mong đợi bộ đệm chuỗi của vô hướng có dấu NUL (mặc dù chiều dài của bộ đệm được biết và mặc dù bộ đệm có thể chứa NUL). Nếu khối bộ nhớ bạn đã cấp có dấu NUL ở cuối dữ liệu (ví dụ: chuỗi ký tự có dạng NUL kiểu C), thì hãy chuyển cờ SV_HAS_TRAILING_NUL. Nếu không, hàm sẽ cố gắng mở rộng bộ đệm và thêm một NUL.

+1

ma thuật cũng có thể được sử dụng để đính kèm một deallocator tùy chỉnh cho SV, thông qua khe 'svt_free'. – salva

Các vấn đề liên quan