'perldoc perlxs'に 'Returning SVs, AVs and HVs through RETVAL'という
項目があって、ここに書いている通りにやると
sub ret_av { ... return @array; } sub ret_hv { ... return %array; }
みたいになるのかなと思って試してみたら違ったということのメモ。
ソース
#include "EXTERN.h" #include "perl.h" #include "XSUB.h" MODULE = HV::Test PACKAGE = HV::Test PROTOTYPES: DISABLE AV* ret_av() CODE: RETVAL = newAV(); sv_2mortal((SV*)RETVAL); av_push(RETVAL, newSViv(10)); av_push(RETVAL, newSViv(20)); OUTPUT: RETVAL HV* ret_hv() CODE: RETVAL = newHV(); sv_2mortal((SV*)RETVAL); hv_store(RETVAL, "name", 4, newSVpv("taro", 4), 0); hv_store(RETVAL, "age", 3, newSViv(28), 0); OUTPUT: RETVAL
xsubppの結果
XS(XS_HV__Test_ret_av) { #ifdef dVAR dVAR; dXSARGS; #else dXSARGS; #endif if (items != 0) croak_xs_usage(cv, ""); { AV * RETVAL; #line 11 "Test.xs" RETVAL = newAV(); sv_2mortal((SV*)RETVAL); av_push(RETVAL, newSViv(10)); av_push(RETVAL, newSViv(20)); #line 94 "Test.c" ST(0) = newRV((SV*)RETVAL); sv_2mortal(ST(0)); } XSRETURN(1); } XS(XS_HV__Test_ret_hv) { #ifdef dVAR dVAR; dXSARGS; #else dXSARGS; #endif if (items != 0) croak_xs_usage(cv, ""); { HV * RETVAL; #line 21 "Test.xs" RETVAL = newHV(); sv_2mortal((SV*)RETVAL); hv_store(RETVAL, "name", 4, newSVpv("taro", 4), 0); hv_store(RETVAL, "age", 3, newSViv(28), 0); #line 119 "Test.c" ST(0) = newRV((SV*)RETVAL); sv_2mortal(ST(0)); } XSRETURN(1); }
それらの値が newRV(Reference Value)となって返ってくる
コードになっていました。
おわりに
あまり直感的ではないので、明示的にリファレンスとして
返すという風に書いた方がいいかなと思いました。
リファレンスを返す例は 'perldoc perlxstut'の EXAMPLE6が
とてもわかりやすかったので、そちらを見るとよいでしょう。