Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello all, I got stuck when I was trying to call a subroutine in .xs file. run h2xs -n Parser... modify Parser.pm:
################################### #!/usr/local/bin/perl package Parser; use 5.008007; use strict; use warnings; require Exporter; require DynaLoader; our @ISA = qw(DynaLoader Exporter); our %EXPORT_TAGS = ( 'all' => [ qw() ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw(); our $VERSION = '1.261'; bootstrap Parser $VERSION; # Preloaded methods go here. ########################################################## sub new { my $class = shift; $class = ref $class if ref $class; my $self = { strip_autos=>0, @_}; bless $self, $class; return $self; } sub read { my $self = shift; my %param = (@_); if (!-r $param{filename}) { print "%Error: file not found: $param{ +filename}, stopped";} $self->_read_xs($param{filename}, $param{strip_autos}||$self->{str +ip_autos});## error comes } ... #In Parser.XS: # sub _read_xs {class} # sub filename {class} # sub lineno {class} ...
Parser.xs (snippet) ...
int _read_xs (CLASS, filename, strip_autos) SV *CLASS char *filename int strip_autos PROTOTYPE: $$$ CODE: { static int/*bool*/ in_parser = 0; if (!SvROK(CLASS)) { in_parser = 0; croak (" Parser::read() not called as class member") ; } if (!filename) { in_parser = 0; croak (" Parser::read() filename=> parameter not passed") ; } if (in_parser) { croak (" Parser::read() called recursively") ; } in_parser = 1; scparse_init (CLASS, filename, strip_autos) ; if (!sclex_open (filename)) { in_parser = 0; croak (" Parser::read() file not found") ; } scgrammerparse(); fclose (sclexin); /* Emit final tokens */ scparser_EmitPrefix (); if (scParserState.errors) { in_parser = 0; croak (" Parser::read() detected parse errors"); } in_parser = 0; RETVAL = 1; } OUTPUT: RETVAL
... a test file named Trialparser.pl is showed below:
#! /usr/local/bin/perl use ExtUtils::testlib; package Trialparser; use Parser; @ISA = qw(Parser); package main; my $sp = Trialparser->new(); $sp->read (filename =>'ExParse.sp');
There was no problem with running perl makefile.pl, make, make test, make install, but an error came out when I trying "perl Trialparser.pl":
Can't locate auto/Trialparser/class.al in @INC (@INC contains: /cygdri +ve/d/parser/blib/arch /cygdrive/d/parser/blib/lib /usr/lib/perl5/5.8/ +cygwin /usr/lib/perl5/5.8 /usr/lib/perl5/site_perl/5.8/cygwin /usr/li +b/perl5/site_perl/5.8 /usr/lib/perl5/vendor_perl/5.8/cygwin /usr/lib/ +perl5/vendor_perl/5.8 .) at /cygdrive/d/parser/blib/lib/Parser.pm lin +e 51
Anyone can help me with me? what does class.al stand for? Any suggestion is welcome, thanks in advance!!!!!

Replies are listed 'Best First'.
Re: An error in using XS
by chromatic (Archbishop) on Jul 11, 2006 at 03:48 UTC

    Line 51 of your Parser module attempts to call an undefined subroutine class. You didn't show that piece of code, but it's almost certainly wrong.

    This error message is likely due to the use of AutoLoader somewhere, which installs an AUTOLOAD() subroutine to catch calls to undefined functions. It then attempts to load the files containing those subroutines. There's no really good reason to do this normally.

      There is no AutoLoader used in my codes. I post whole codes this time, please check it again. Thank you so much! Parser.pm Parser.xs

        Welcome to perlmonks ming_322. I hope you find the answers you are looking for here. Why not just write the parser in perl? Maybe using dispatch tables? Just a thought.

        Thats a lot of code for us to wade through. Could you factor it into a smaller subset that exhibits the same error? It would seem that you wouldn't need all the parser code to reach the same error. You could stub that out.

        I have to agree with chromatic your code attempting to call a subroutine "class". Probably a parameter passing error somewhere.


        s//----->\t/;$~="JAPH";s//\r<$~~/;{s|~$~-|-~$~|||s |-$~~|$~~-|||s,<$~~,<~$~,,s,~$~>,$~~>,, $|=1,select$,,$,,$,,1e-1;print;redo}