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

[Note: The following is a more thorough treatment of a lamer, earlier post (and is x-posted to usenet as well)]

Hullo,

I'm calling code in a perl module from C. The problem is that since I'm loading the module via load_module() my Carp calls all break -- apparently because there's no caller to reference back to.

I'd appreciate any suggestions or insight into this.

= My C =====================================================
#include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; EXTERN_C void xs_init(pTHX); int main(int argc, char **argv, char **env) { char *my_argv[] = { "", "/dev/null" }; int count; SV *ex; /* the object */ char buf[] = "some arbitrary data"; int bufsiz; PERL_SYS_INIT3(&argc, &argv, &env); my_perl = perl_alloc(); perl_construct(my_perl); /* parse the "file" */ perl_parse(my_perl, xs_init, 2, my_argv, (char **) NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); dSP; /* Load the module */ load_module(PERL_LOADMOD_NOIMPORT, newSVpvn("Ex", 2), newSVnv(0.01)); ENTER; /**************************************************************/ SAVETMPS; /* instantiate an object */ PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpvn("Ex", 2))); PUTBACK; count = call_method("new", G_SCALAR); SPAGAIN; if (count != 1) croak("Something weird with Ex::new()\n"); ex = POPs; /* call a method */ bufsiz = strlen(buf); /* just an example, after all */ PUSHMARK(SP); XPUSHs(ex); XPUSHs(sv_2mortal(newSVpvn(buf, bufsiz))); XPUSHs(sv_2mortal(newSViv(bufsiz))); PUTBACK; count = call_method("do_something", G_SCALAR); SPAGAIN; if (count != 1) croak("Something weird with $ex->do_something()\n"); FREETMPS; LEAVE; /**************************************************************/ perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
= My Perl module =====================================================
package Ex; use warnings; use strict; use Data::Dumper; use Carp; our $VERSION = '0.01'; sub new { my $class = shift; my %args = @_; my $self = \%args; bless $self, $class; return $self; } sub do_something { my $self = shift; warn qq(\n"caller()"\n) . Dumper( [ caller() ] ) . "\n"; warn qq("warn"ing); carp qq("carp"ing); print qq(you gave me "$_[0]"\n); return; } 1;
= the Output =========================================================
"caller()" $VAR1 = [ 'main', '/dev/null', 0 ]; "warn"ing at lib/Ex.pm line 21. "carp"ing at /dev/null line 0 you gave me "some arbitrary data"

Replies are listed 'Best First'.
Re: Embedding: load_module(), stack frames and Carp
by ruzam (Curate) on May 26, 2006 at 02:32 UTC
    I think you answered your own question?
    "apparently because there's no caller to reference back to"

    What is it you were expecting carp to report?
      Well, the caller is the C call that's, um, calling the perl code. As far as expectations go, I suppose initially that I naively expected Carp to report that, but of course that's not going to happen as it is.

      Expectations aside, I would like to affect the same thing that Carp would normally do. The module is being used both from C and from Perl, so the solution must be general. Maybe I could subclass Carp so that it will report differently in the case of no call-stack (*now* maybe I'm answering my own question :^).

      The whole thing with passing perl_parse() "/dev/null" feels less than clean as well. How is this normally handled?

      Whatever I do, I was hoping to follow convention -- if there is any -- and that's why I'm laying this out here. What *do* folks do when they load_module() code that contains Carp?

        I'm not sure I understand. Carp breaks? Or Carp doesn't return what you expect?

        Disclaimer: I've never tried anything even remotely like this...

        As far as I can tell from your example and other examples found on google, where you've put "/dev/null" is where others normally put the name of the calling file, which would be in keeping with the results returned by caller(). I could make an assumption (which is probably wrong), that my_argv as you've used it, would contain the package, file, line that would be returned by caller (and carp). Package defaulting to 'main' (as it's blank) and line defaulting to zero (as it's blank as well). Since my_argv is passed as a pointer, it may be that you can change the values before each call to call_method() in your C code, like say set the line number to the line number in your C code before making the call. Or it may be that the my_argv values are copied by perl_parse() and you can't change them later. But this is all purely speculation, take it for what it's worth.