2017-10-12 17 views
8

Sử dụng XS tôi đang cố chuyển giá trị từ mảng C vào một mảng Perl có thể được sử dụng trong tập lệnh.perl xs - trả về mảng perl từ mảng c

Đây là mã từ file xs tôi:

AV * 
DoubleArray::getPerlArray() 
    CODE: 
    r = newAV(); 
    for(size_t i=0; i < THIS->count; i++) 
    { 
     av_push(RETVAL,newSVnv(THIS->data[i])); 
    } 
    OUTPUT: 
    RETVAL 

Nó biên dịch tốt nhưng khi tôi chạy sau trong perl:

my @d = $C->getPerlArray(); 
foreach(@d) 
{ 
    print "$_\n"; 
} 

Nó chỉ in ARRAY(0x1408cdc) khi tôi mong nó để in một danh sách các số.

Làm cách nào để sửa đổi mã của mình để trả lại chính xác mảng perl?

+0

https://www.nntp.perl.org/group/perl.xs/2011/06/msg2626.html dường như có liên quan – simbabque

+0

@simbabque Tôi đã xem ví dụ đó trước đây. Đó là một mớ hỗn độn. Khó học hỏi từ. –

+0

Bạn có muốn chia sẻ một số điều bạn đã học được với cộng đồng không? Bạn có thể thêm một hoặc hai chương vào https://github.com/xsawyerx/xs-fun. :-) – simbabque

Trả lời

9

Công cụ đăng ký Perl chỉ có thể trả về (0 hoặc nhiều hơn) vô hướng. Khi bạn cố gắng trả về một mảng (không thể không bị rơi Perl!), Typemap mặc định trả về một tham chiếu tới mảng đó.

Lưu ý rằng chương trình của bạn cũng bị rò rỉ bộ nhớ (vì typemap mặc định cho AV* sẽ làm chết mảng của bạn nhưng không).


Trả về một tài liệu tham khảo, phương pháp 1

AV* /* Returns: sv_2mortal(newRV(RETVAL)) */ 
DoubleArray::getPerlArrayRef() 
    PREINIT: 
     size_t i; 
    CODE: 
     RETVAL = (AV*)sv_2mortal((SV*)newAV()); 
     for (i=0; i < THIS->count; ++i) { 
      av_push(RETVAL, newSVnv(THIS->data[i])); 
     } 

    OUTPUT: 
     RETVAL 

Memory rò rỉ séc:

  • Array Avatar của refcnt: 1 (newAV) -1 [hoãn] (sv_2mortal) + 1 (newRV) = 1 [bị trễ] (thuộc sở hữu b y tham khảo)
  • refcnt tham khảo của: 1 (newRV) -1 [hoãn] (sv_2mortal) = 0 [hoãn]

Perl:

my $array = $C->getPerlArrayRef(); 
say for @$array; 

Trở tham chiếu, phương pháp 2

SV* /* Returns: sv_2mortal(RETVAL) */ 
DoubleArray::getPerlArrayRef() 
    PREINIT: 
     AV* av; 
     size_t i; 
    CODE: 
     av = newAV(); 
     RETVAL = newRV_noinc((SV*)av); 
     for (i=0; i < THIS->count; ++i) { 
      av_push(av, newSVnv(THIS->data[i])); 
     } 

    OUTPUT: 
     RETVAL 

Memory rò rỉ séc:

  • Array Avatar của refcnt: 1 (newAV) +0 (newRV_noinc) = 1 (thuộc sở hữu của tài liệu tham khảo)
  • tham khảo của refcnt: 1 (newRV_noinc) -1 [hoãn] (sv_2mortal) = 0 [hoãn]

Perl: < tương tự như trên>


Trả về một tài liệu tham khảo, phương pháp 3

void 
DoubleArray::getPerlArrayRef() 
    PREINIT: 
     AV* av; 
     size_t i; 
    PPCODE: 
     av = newAV(); 
     mXPUSHs(newRV_noinc((SV*)av)); 
     for (i=0; i < THIS->count; ++i) { 
      av_push(av, newSVnv(THIS->data[i])); 
     } 

Memory rò rỉ séc:

  • refcnt Array Avatar của: 1 (newAV) +0 (newRV_noinc) = 1 (thuộc sở hữu của tài liệu tham khảo)
  • Tham chiếu của refcnt: 1 (newRV_noinc) -1 [bị trì hoãn] (mXPUSHs) = 0 [hoãn]

Perl: < tương tự như trên>


vô hướng Trở

Chúng ta phải kiểm tra bối cảnh vì chúng ta không thể diễn ra nhiều hơn một vô hướng trên ngăn xếp bên ngoài ngữ cảnh danh sách.

void 
DoubleArray::getElements() 
    PREINIT: 
     size_t i; 
     U8 gimme = GIMME_V; 
    PPCODE: 
     if (gimme == G_ARRAY) { 
      EXTEND(SP, THIS->count); 
      for (i=0; i < THIS->count; ++i) { 
       mPUSHn(THIS->data[i]); 
      } 
     } 
     else if (gimme == G_SCALAR) { 
      mXPUSHu(THIS->count); 
     } 

Perl:

my $count = $C->getElements(); 
say $count; 

my @array = $C->getElements(); 
say for @array; 

Lưu ý: Lượng giảm refcnt bởi sv_2mortal bị trì hoãn cho đến khi người gọi có một cơ hội để tăng refcnt.

+2

Câu trả lời hay! Cảm ơn! –

+0

Câu trả lời hay! Lưu ý cho phiên bản Perl> = 5.16, bạn cũng có thể khai báo typemap 'AV * \t T_AVREF_REFCOUNT_FIXED' nếu bạn không quan tâm đến tính tương thích ngược, xem phần *" Trả về SV, AV và HV qua RETVAL "* trong [' perlxs'] (https://perldoc.perl.org/perlxs.html#Returning-SVs%2c-AVs-and-HVs-through-RETVAL) để biết thêm thông tin. –

+0

Vâng, đã tìm ra câu trả lời đã đủ dài mà không giới thiệu điều đó. – ikegami

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