in reply to Re: XS: Passing an external library's function a Perl XS callback
in thread SOLVED: XS: Passing an external library's function a Perl XS callback

Do you mean within callback()? I put those lines before and after the call to the actual perl sub, but both cases still result in segfault.

  • Comment on Re^2: XS: Passing an external library's function a Perl XS callback
  • Download Code

Replies are listed 'Best First'.
Re^3: XS: Passing an external library's function a Perl XS callback
by Anonymous Monk on Aug 14, 2016 at 21:21 UTC

      I greatly appreciate the feedback to try, AnonyMonk!

      With the last code, static didn't work, so I removed that. I also initialized a and b. This very slightly modified declaration (yep, I corrected the def as well):

      void callback(){ int a = 10; int b = 20; dSP; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSViv(a))); XPUSHs(sv_2mortal(newSViv(b))); PUTBACK; call_pv("p_callback", G_DISCARD|G_NOARGS); SPAGAIN; printf("%d to the %dth power is %d.\n", a, b, POPi); PUTBACK; FREETMPS; LEAVE; }

      ...with the exact same otherwise all around, produces:

      in init in perl callback Use of uninitialized value in subroutine entry at c_extern_call_perl.p +l line 11. 10 to the 20th power is -474476032. Segmentation fault

      So, callback() is working perfectly on the direct call from the perl code, it still registers ok in the external function, but as soon as the callback is triggered from extern, it breaks, from my estimation, at or before the call to call_pv().

      Update: I moved around some comments, and it segfaults on anything following the call to dSP().

      Perhaps I'm XY Problem-ing this. Here's what I want...

      • extern C function requires a void func(void) function pointer as a callback
      • I would really prefer not to modify the external code, if I can avoid it (I'd really like it to be void func(const char *string) realistically, I think, but I am a C newb)
      • to avoid the void/void, on the perl side, I want a user to send in a cref to a Perl method, which calls an XSUB to send in a pre-defined XSUB callback that points to the cref to the external C function (this all works)
      • when an event is triggered, and the already-registered callback in the extern is called, it should call the user-supplied cref in the main module's (in the case I've exampled here, the main script) perl code

      Am I making sense here? Perhaps I'm thinking this totally wrong. I'm going to keep pounding on this because I know there's got to be a way :) I'm just not experienced enough in all of the cross-language comms, and using XS. I'm having fun though

        Try starting with something that works, and then add to it.
        For example, I have no trouble with:
        use warnings; use strict; use Inline ('C' => 'DATA'); callback(); sub p_callback { print "in perl callback\n"; } __DATA__ __C__ void callback(){ dSP; PUSHMARK(SP); call_pv("p_callback", G_DISCARD|G_NOARGS); }
        Does that work ok for you ? Make sure there's an empty line after the end of the C code.
        I don't have libwiringPi, and can't really help with the rest. (If I don't have code that I can actually test then I'm likely to end up presenting misinformation.)

        Are you aware of the Inline::C configuration option CLEAN_AFTER_BUILD=>0
        It leaves the build directory intact so you can actually inspect the generated XS file and C file - which is sometimes helpful when things aren't working as expected.

        Cheers,
        Rob