2016-12-15 15 views
9

Đọc perlxs documentation, tôi đến phần trên từ khóa OUTPUT:Tại sao bao gồm SvSETMAGIC() trên các biến đầu ra trong một XSUB?

xsubpp phát ra một tự động SvSETMAGIC() cho tất cả các thông số trong phần OUTPUT của XSUB, trừ retval. Đây là hành vi thường được mong muốn , vì nó sẽ chăm sóc đúng cách gọi phép thuật 'set' trên đầu ra tham số (cần cho tham số phần tử băm hoặc mảng phải được tạo nếu chúng không tồn tại).

Tôi không chắc mình hiểu tại sao là set ma thuật là mong muốn (và tại sao nó không được mong muốn cho RETVAL)? Và tại sao cần có ma thuật set cho tham số phần tử băm và mảng?

Trả lời

6

Tất cả các cấu trúc dữ liệu của Perl hỗ trợ kỳ diệu, không chỉ SV s (mặc dù tên) và đặc biệt cho băm và mảng này là cơ sở cho những thứ như cơ chế tie hay những thứ như fieldhash mà thực hiện một chất tương tự của tài liệu tham khảo yếu ở mức độ của các mục nhập băm.

Chỉ thị OUTPUT cho biết đối số nào có thể được sửa đổi bởi nội dung C của XSUB và biến có chứa ma thuật thiết lập có thể được chuyển vào, đặt giá trị theo typemap mà không gọi trình xử lý có thể dẫn đến không nhất quán hành vi.

use Scalar::Util qw(weaken); 

my $foo; 
my $ref = \$foo; 
weaken($ref); 

Như một ví dụ về ma thuật, weaken decrements đếm tham chiếu của $foo, và cho biết thêm kỳ diệu chỉ trở lại $ref để nó được xóa nó khi $foo được thu gom rác thải.

Bên cạnh đó, nó cũng cho biết thêm thiết lập ma thuật để $ref, xé xuống trở lại này tham khảo, nếu không khi $foo bị phá hủy, $ref sẽ được xóa mặc dù vào thời điểm này nó không còn chỉ vào $foo.

Nếu bạn sử dụng $ ref như một cuộc tranh cãi, nó được aliased trên stack (đó là lý do $_[0] is assignable):

modifies_arguments($ref); 

sub modifies_arguments { 
    $_[0] = "blah"; # set magic is invoked to tear down the back referencing 
} 

Nếu modifies_arguments là một Perl tinh khiết thật dễ dàng để xem tại sao điều này là thích hợp, nhưng giả định tương tự về tính chính xác tất nhiên phải giữ cho XSUB, đó là lý do tại sao OUTPUT được sử dụng để đánh dấu đối số nào sẽ đặt giá trị của chúng thành bất kỳ biến đối số cấp C nào ở cuối thân hàm và đặt ma thuật được kích hoạt.

Điều này không áp dụng cho RETVAL, vì đó không phải là bài tập kỹ thuật, mà là đẩy SV mới lên ngăn xếp và bất kỳ phép thuật nào sẽ được xử lý sau khi hàm trả về chuyển nhượng (nếu có).

+0

Cảm ơn bạn đã làm rõ điều này! Điều gì về các văn bản trích dẫn trong ngoặc đơn: * '" cần thiết cho các tham số phần tử băm hoặc mảng phải được tạo ra nếu chúng không tồn tại "' *? Điều này" nói đến cái gì? Nó có nghĩa là ma thuật 'set' không được áp dụng cho vô hướng hay cái gì khác? –

+0

'my @array; modifies_arguments ($ array [42]) 'sẽ chỉ tạo thành phần mảng khi nó thực sự được sửa đổi, cf. autovivification. Nếu mảng là huyền diệu, thì điều này sẽ liên quan đến việc thiết lập phép thuật trên chính mảng đó. Tuy nhiên, điều này vẫn áp dụng cho vô hướng, như trong ví dụ '$ ref' ở trên. – nothingmuch

2

Nó khá đơn giản. Bất cứ khi nào bạn gán cho một vô hướng, bạn cần phải gọi SvSETMAGIC() trên nó sau đó trong trường hợp nó có ma thuật liên kết với nó.

Gán cho RETVAL không gán cho biến Perl, do đó, hãy gọi SvSETMAGIC(RETVAL) (trừ khi bạn đã thực sự sửa đổi RETVAL) sẽ là sai.Nếu giá trị trả về được gán cho một vô hướng khác trong người gọi, thì nhiệm vụ sẽ gọi SvGETMAGIC trên giá trị trả lại trước khi gán, và SvSETMAGIC trên biến được gán sau khi gán.

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