When "use encoding utf8" is called, substr() changes SvTYPE of its argument

[email protected] (Eduardo M KALINOWSKI)
Newsgroups perl.xs
Message-ID <[email protected]>
     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
[email protected]
test.c (text/x-csrc, 1.3 KB)
/* 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, "");
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.