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, "");
}

Reply via email to