I've encountered a weird situation which the attached program
demonstrates:
- I create a Perl interpreter, and define the "displayarg"
function that calls the XS_displayarg() C function. This function
prints the type of its arguments as returned by SvTYPE.
- I then execute the perl code
my $s = "s";
displayarg($s);
which prints, as expected, that the type of the argument is 5, SVt_PV.
- However, if I change the code to
my $s = "s";
substr($s, 0, 1);
displayarg($s);
then the type of the argument is 8, SVt_PVMG, "Blessed or
Magical Scalar".
I really do not know why that happens. I understand that the return
value of substr() is in a way "magical", but I'm not using the return
value; instead, the type of the actual variable has been changed.
Furthermore, i notice that only happens if "use encoding utf8" is
active (in the example, activated by passing "-Mencoding=utf8" as an
argument when creating the interpreter, but actually executing "use
encoding utf8" produced the same behavior).
--
Democracy is a process by which the people are free to choose the man who
will get the blame.
-- Laurence J. Peter
Eduardo M KALINOWSKI
edua...@kalinowski.com.br
/* Compile with
gcc -g -Wall -O0 -o test test.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
*/
#include <stdio.h>
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>
void xs_init();
EXTERN_C void boot_DynaLoader(pTHX_ CV* cv);
int main(int argc, char *argv[])
{
char *embed[] = { "", "-Mencoding=utf8", "-e", "0" };
// If utf-8 is removed, it works as expected:
//char *embed[] = { "", "-Mencoding=utf8", "-e", "0" };
PerlInterpreter *perl;
PERL_SYS_INIT(&argc, &argv);
perl = perl_alloc();
perl_construct(perl);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_parse(perl, xs_init, 4, embed, NULL);
// This works
eval_pv("my $s = \"s\";"
"displayarg($s);", TRUE);
// This does not
eval_pv("my $s = \"s\";"
"substr($s, 0, 1);"
"displayarg($s);", TRUE);
perl_destruct(perl);
perl_free(perl);
PERL_SYS_TERM();
return 0;
}
void
XS_displayarg(pTHX_ CV *perlcv)
{
dXSARGS;
int argpos = 0;
while (argpos < items) {
SV *sv = ST(argpos);
printf("arg type: %d\n", SvTYPE(sv));
++argpos;
}
XSRETURN_EMPTY;
}
void
xs_init()
{
char *file = __FILE__;
dXSUB_SYS;
/* DynaLoader is a special case */
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
newXS("displayarg", XS_displayarg, "");
}