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

Hello Perl Gurus,

I am having trouble updating a variable in a perl sub and using the updated value in the main body of the perl script. Ultimately, I'd like to share more complex data between the sub/callback and main. Any help would be greatly appreciated!

I am extending perl (with SWIG) to access a C library and also embedding a perl interepreter (via perl_clone) so that the library can invoke perl subroutines as callbacks.

The perl subs are getting called correctly. I need to wait in the main perl script until the callback is executed before other actions are taken. I initially initialized a simple scalar to "0" and changed its value in the subroutine and waited (sleep() ) until the value is updated. Though the callback updates the value, it is never reflected in the main body of the script. I'm not sure what is the reason?

As a possible solution, I declared the scalar as ":shared", but then I get this error on a unrelated line of code. The offending line is registering the perl-sub as a callback into the C library via a SWIG generated wrapper. Not sure of the link between "use threads:shared" and this message.

Perl version 5.8.8 threads version: 1.07, threads::shared version: 0.94

Original/ideal looking code sample..
#This is the SWIG generated module to my C library use MyModule; #shared scalar $cb_done = 0; #This cb would be invoked by the cloned interpreter in the #C library. This works fine. sub cb_one { ($event, $pdata) = @_; #This line is printed. print "event : ", $event, "\n"; $cb_done = 1; } $status = MyModule::RegisterCB(\&main::cb_one); do { sleep (5); } until ($cb_done == 1) #This line is not printed as $cb_done never becomes 1 #in the main of the perl script print "CB was invoked : $cb_done\n";

Sample code using threads::shared

use threads; use threads::shared; use MyModule; #shared scalar $cb_done : shared = 0;
But I get "Invalid value for shared scalar" for this line of code

 $status = MyModule::RegisterCB(\&main::cb_one);

  • Comment on Extending & Embedding Perl simultaneously: How to share a scalar between perl callback sub and main body?
  • Select or Download Code

Replies are listed 'Best First'.
Re: Extending & Embedding Perl simultaneously: How to share a scalar between perl callback sub and main body?
by BrowserUk (Patriarch) on Dec 01, 2009 at 13:22 UTC

    Try prefixing you global var with our:

    our $cb_done :shared = 0;

    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.
Re: Extending & Embedding Perl simultaneously: How to share a scalar between perl callback sub and main body?
by cdarke (Prior) on Dec 01, 2009 at 13:41 UTC
    Works for me (ActiveState Perl 10.1 on Windoze).

    Did you miss the syntax error in your code (missing ; after until)? Try use warnings;

    Here is my C:
    #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #include "const-c.inc" MODULE = MyModule PACKAGE = MyModule INCLUDE: const-xs.inc int RegisterCB (SV *SubRef) CODE: ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpv("Some event",0))); XPUSHs(sv_2mortal(newSVpv("Some pdata",0))); PUTBACK; call_sv(SubRef, G_DISCARD); FREETMPS; LEAVE; RETVAL = 1; OUTPUT: RETVAL
    Here is the Perl (its a long time since I didn't use strict;):
    use MyModule; use warnings; #shared scalar $cb_done = 0; #This cb would be invoked by the cloned interpreter in the #C library. This works fine. sub cb_one { ($event, $pdata) = @_; #This line is printed. print "event : ", $event, "\n"; $cb_done = 1; } $status = MyModule::RegisterCB(\&main::cb_one); do { sleep (5); } until ($cb_done == 1); #This line is printed as $cb_done becomes 1 #in the main of the perl script print "CB was invoked : $cb_done\n";
    and here is the output:
    C:\gash\MyModule>test.pl Name "main::pdata" used only once: possible typo at C:\gash\MyModule\t +est.pl line 11. Name "main::status" used only once: possible typo at C:\gash\MyModule\ +test.pl line 17. event : Some event CB was invoked : 1

    Update: original code was not passing parameters to the callback.
    Update 2: I hadn't freed the temporaries and closed the scope

      My guess would be the problem is that the OP is using perl_clone() (which you are not), and that the callback code is being executed in the wrong (cloned) interpreter.   (As usual, it would help to see the OP's actual code, though...)

        Thanks for all the comments!

        Apologies for typo in the code sample. I tried prefixing "our", but that didnt change the result.

        As almut said, I am using a cloned interpreter and the perl sub/callback is executed in the cloned interpreter context. So, is the problem in how I'm cloning it? Or does cloning by definition mean, I cannot "share". Here is a post describing how I've done the embedding.

        One "crude" way I can think of is to implement a "shared memory" API on C side to save/retrieve data between the subs and main. Perhaps CPAN has modules like this already..but I'm really hoping there is a more "natural" solution.

        http://markmail.org/thread/cjbhybjfikuirvud

        http://markmail.org/thread/inetppjegt5iecl5