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

Hi, I'm currently writting a module in perl XS and I would like to output the package name, the function name, the perl line number when I use the XS function die("..."). Are there any XS macros for that ? Can someone provide an example ?
  • Comment on Output package and function name as well as linenum in a die in XS

Replies are listed 'Best First'.
Re: Output package and function name as well as linenum in a die in XS
by chromatic (Archbishop) on Sep 04, 2006 at 18:20 UTC

    You can call Carp's croak() from XS.

Re: Output package and function name as well as linenum in a die in XS
by syphilis (Archbishop) on Sep 05, 2006 at 07:34 UTC
    Can you simply call croak(), with argument(s) that specify the package name and the function name ? Perl will take care of the line number for you:
    ## test.pl ## package MYFOO; use warnings; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'EOC'; void foo() { croak("Package MYFOO, function foo() croaked"); } EOC MYFOO::foo(); #line 15 __END__ Outputs: Package MYFOO, function foo() croaked at test.pl line 15.

    Cheers,
    Rob
      You can, but manually inserting that kind of info every time gets old. That's why it's worth the initial trouble to set it up so that contextual information gets inserted automatically.
      package MyFoo; use strict; use warnings; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'EOC'; #line 9 "die_in_context.plx" #define MY_PACKAGE "MyFoo" #define kick_bucket(...) \ do_kick_bucket(__FILE__, __LINE__, MY_PACKAGE, __func__, __VA_ARGS +__) void do_kick_bucket(const char *file, I32 line, const char *package, const char *func, const char *pat, ...) { va_list args; SV *error_sv = newSVpvn("", 0); va_start(args, pat); sv_vcatpvf(error_sv, pat, &args); va_end(args); sv_catpvf(error_sv, " at function %s::%s at %s line %d\n", package, func, file, line); die(SvPVX(error_sv)); } void foo() { kick_bucket("Bad Juju"); } EOC MyFoo::foo(); __END__ Outputs: Bad Juju at function MyFoo::foo at die_in_context.plx line 30

      The package in XS functions you ordinarily get for free, because it's part of the function name and thus gets picked up by the __func__ macro. For example when I insert a call to my Confess macro into KinoSearch::Store::InStream::new, the stack trace starts like this...

      Error in function XS_KinoSearch__Store__InStream_new at lib/KinoSearch +.xs:1742: Kill me now

      __VA_ARGS__ and __func__ are C99, though, so if you need portability you have to probe for them at build time and set up alternatives for when they aren't available.

      --
      Marvin Humphrey
      Rectangular Research ― http://www.rectangular.com
Re: Output package and function name as well as linenum in a die in XS
by creamygoodness (Curate) on Sep 05, 2006 at 03:19 UTC

    Here's code from KinoSearch::Util::Carp, which calls Carp::confess from C.

    void Kino_confess (char* pat, ...) { va_list args; SV *error_sv; dSP; error_sv = newSV(0); va_start(args, pat); sv_vsetpvf(error_sv, pat, &args); va_end(args); ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs( sv_2mortal(error_sv) ); PUTBACK; call_pv("Carp::confess", G_DISCARD); FREETMPS; LEAVE; }

    It assumes that somewhere, someone has invoked use Carp;.

    If you know that either ISO or GNU variadic macros are available, you can transparently insert the filename and the line number of the C file from where the exception was thrown, plus the function if either __func__ (C99) or __FUNCTION__ (GNU) is defined. Take a look at KinoSearch::Util::Carp in my svn repository if you want to see how that can work.

    The bonus contextual info is just plain ol' nasty C wrangling though -- the XS-specific stuff is the same. Check out perlcall for more info on how to call back to Perl from C.

    --
    Marvin Humphrey
    Rectangular Research ― http://www.rectangular.com