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

Hi Monks,

Before the question, this is my system structure:
Perl calls C code that calls a Perl CallBack (Perl-->C-->Perl CB).

I would like that the Perl callback will use the interpreter which used by the "1st" Perl script.

Currently, I'm creating a new interpreter for the callback by calling perl_alloc(), but it is not good enough...


Any clue is most welcomed :)


Many thanks,

Itamar

  • Comment on Perl calls C calls Perl CallBack: How Perl callback use the same interpreter/context as Perl caller?

Replies are listed 'Best First'.
Re: Perl calls C calls Perl CallBack: How Perl callback use the same interpreter/context as Perl caller?
by Corion (Patriarch) on Jul 08, 2014 at 09:09 UTC

    perlcall seems to suggest simply using call_sv(). I don't know where exactly you encounter problems, so maybe showing a bit of the relevant code maybe helps.

      Hi,

      Appreciate your response!

      In general the flow of my current code is divided to 5 stages(as seen bellow):
      1. Create an interpreter (my_perl)
      2. Push parameters to the Perl stack (XPUSHs)
      3. Call Perl function (call_pv)
      4. POP return value (POPi)
      5. Destruct the interpreter

      Code wise, stages 2 and 4 depends on the existance of 'my_perl' interpreter pointer (XPUSHs and POPi macros are using it).

      How can I get a pointer to the interpreter of the Perl function that called the C code? Should I use other macros?


      Thanks a lot for your help :)


      Itamar


      HV* my_hash; AV* my_arr; int retVal = 0; char* my_argv[] = { "", cb->cbFunc.perlCbFunc.fileName }; // PERL interpreter creation my_perl = perl_alloc(); perl_construct( my_perl ); // PERL interpreter initiation perl_parse( my_perl, // The interpreter NULL, // XSINIT value - Should be NULL if no + external modules are being used 2, // Number of entries in 'my_argv' my_argv, // PERL 'command line'. (char **)NULL); // ENV, not relevant for our usage // Run the PERL interpreter perl_run(my_perl); // Call a PERL function dSP; /* Ini +tialize stack pointer */ ENTER; /* Eve +rything created after here */ SAVETMPS; /* ... +is a temporary variable. */ PUSHMARK(SP); /* Rem +ember the stack pointer */ XPUSHs(sv_2mortal(newSViv((unsigned int)cbCtx))); /* Pus +h callback context onto stack */ my_hash = newHV(); my_arr = newAV(); hv_store( my_hash, "aaaaaa", 6, newSViv(1), 0 ); hv_store( my_hash, "bbb", 3, newSViv(2), 0 ); hv_store( my_hash, "cccccccccc", 10, newSViv(3), 0 ); hv_store( my_hash, "ddddddddd", 9, newSViv(4), 0 ); hv_store( my_hash, "eeeeeee", 7, newSViv(5), 0 ); hv_store( my_hash, "ffff", 4, newSViv(6), 0 ); hv_store( my_hash, "gggggg", 6, newSViv(7), 0 ); hv_store( my_hash, "hhhhhhh", 7, newSViv(8), 0 ); for ( int i = 0; i < 50; i++ ) { av_push( my_arr, newSViv((unsigned int)arr[i]) ); } // Store reference to parameters on the HASH hv_store( my_hash, "arr", 6, newRV((SV*)my_arr), 0 ); XPUSHs( sv_2mortal(newRV((SV*)my_hash)) ); PUTBACK; /* Mak +e local stack pointer global */ call_pv( funcName, G_SCALAR ); /* Cal +l the function */ retVal = POPi; /* POP + the return of the PERL function */ SPAGAIN; /* Ref +resh stack pointer */ PUTBACK; FREETMPS; /* fre +e that return value */ LEAVE; /* ... +and the XPUSHed "mortal" args */ // Destruct PERL interpreter perl_destruct(my_perl); perl_free(my_perl);

        I think that basically you will have to make my_perl a global variable so that it is available everywhere. You could also pass the information through Perl as an integer (SvIV), but that makes for a horribly brittle design.

Re: Perl calls C calls Perl CallBack: How Perl callback use the same interpreter/context as Perl caller?
by BrowserUk (Patriarch) on Jul 08, 2014 at 12:00 UTC

    You may find the thread at Perl crash during perl_clone contains a lot of relevant information.

    Be warned. It is a long and deep thread with much of the best information coming towards the end; down around Re^24: Perl crash during perl_clone.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Hi,

      Thanks for your reply!

      I've tried to use Perl_get_context() (or dTHX) and got NULL.

      Currently, I don't understand how to get the pointer of the interpreter of the Perl function that calls the C function.

      My system structure:
      Perl function --> C DLL --> Perl Callback

      The requirement is that the Perl function and the Perl callback will work from the same context.


      Many thanks and best regards,

      Itamar

        May your C DLL be loading and using Perl.DLL to resolve symbols instead of linking back to the perl executable?
Re: Perl calls C calls Perl CallBack: How Perl callback use the same interpreter/context as Perl caller?
by locked_user sundialsvc4 (Abbot) on Jul 08, 2014 at 20:09 UTC

    One general flow-of-control that I have used in similar situations is to equip the (C ...) DLL with a separate subroutine that the external context can call, in order to give it, ahead of time, the bit of information that the library will need to use later.   This bit of data must then be stored in thread-local storage by the DLL.   (The library’s initialization routine should explicitly set that slot to NULL.   Thus, if the slot is found to already contain a non-NULL value when this routine is called, an exception should be thrown.)

    Before attempting to make the call, the DLL should verify that the slot contains a non-NULL value, and if it does, may assume that it contains the magic bit of data that is required.   (If not, the library should throw an exception.   The library should also be prepared to trap an exception occurring from the external call [to Perl ...], when that is attempted.)

    For completeness, there should also be a second, “bye-bye, I’m going away now ...” entry-point in the DLL, whose sole purpose is to set that slot to NULL again, after doing any additional tear-down that may be required.   (If the slot is found to be NULL upon entry, this call is a no-op.)

    Not Perl-specific, and “more than a bit of a hack,” but it works reliably.   (The suspicious, “throw an exception if anything smells funny” safeguards are a big part of that reliability.)