'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が
とてもわかりやすかったので、そちらを見るとよいでしょう。