Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

How do I pass a reference to another program via @ARGV ???

by aplonis (Pilgrim)
on Dec 16, 2006 at 19:28 UTC ( [id://590225]=perlquestion: print w/replies, xml ) Need Help??

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

I have a Tk program for controlling a stepper motor using the Device::LabJack module. Problem is that the module method for sending pulses (to run the stepper) does not return until the stepper has stopped...some 20 seconds or more. And the stepper is moving for 90% of the program. So the Tk interface is 90% frozen, inactive, playing dead...making the program itself appear crashed.

I figured to isolate the stepper-move code into a separate file and launch it via Win32::Process but I need for it to pass back (without hanging Tk) the stepper counts it actually made. I was hoping to pass it a reference which Tk can check via $mw->waitVariable(\$foo). How do I do that? How do I pass a reference to the new process so that the launched script can read it via @ARGV?

Replies are listed 'Best First'.
Re: How do I pass a reference to another program via @ARGV ???
by zentara (Archbishop) on Dec 16, 2006 at 21:22 UTC
    Here are a couple of simple scripts to help get you going. The script below just shows a simple thread which can do the stepper control, without blocking the gui. The important point is that the main Tk thread, will not be able to update textvariables automatically from the thread. So you need a timer running, to check the shared vars, and set the textvariables to their values. And as a bonus, here is a link which should show you how to make graphic of the motor position. See Tk compass dial. You could make one with 2 arrows, one for setting the motor, and a second for displaying the feedback position.

    Simple thread with feedback:

    #!/usr/bin/perl use warnings; use strict; use Tk; use threads; use threads::shared; my $go : shared; my $die : shared; my $step_set : shared; my $feedback : shared; $go = 0; $die = 0; $step_set = 0; $feedback = 0; my $repeater; my $stepper = 0; my $feedback_display = 0; my $thread = threads->new(\&work); my $mw = MainWindow->new( -title => "Stepper Test" ); my $entry = $mw->Entry(-textvariable => \$stepper)->pack(); my $indicator = $mw->Label(-textvariable => \$feedback_display)->pack( +); $mw->Button(-text=>'Start Stepper', -command=> sub { $step_set = $stepper; $go = 1; # timer to read shared vars $repeater = $mw->repeat(10,sub{ $feedback_display = $feedback; if( $feedback_display == $stepper){ $go =0; } }); })->pack(); $mw->Button(-text=>'Exit', -command=> sub { $go = 0; $die = 1; # must return before joining $repeater->cancel; # JOIN ALL THREADS foreach my $thread (threads->list) { $thread->join; + } exit; })->pack(); MainLoop; sub work{ $|++; while(1){ if($die == 1){ return }; if ( $go == 1 ){ for(0..$step_set){ print "$_\n"; $feedback = $_; select(undef,undef,undef,.5); } }else { sleep 1 } } }

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum

      That is excellent. Thank you! Your concise example is very fine. It's short and sweet and it runs as is on NetBSD (where I'm browsing from). Thanks very much indeed.

      It's late tonight, but I'm copying it to flash memory for adapting to my Win32 program on the laptop tomorrow. Come Monday I'll try it out on the machine in question.

      FYI -- My particular stepper motor application is to dial up a 20-turn needle valve in a test rig cycling pressure (ramp up, hold, ramp down) thousands of times on a jet engine fuel nozzle. Have to do it that way because this is for a contamination test. The fluid in question is JP-8 jet fuel loaded with calibrated dirt (hematite, rust, Arizona road dirt and lint) and no proportinal or servo-valve would last even 10% of the test.

        FINAL REPORT

        It works exactly as advertized! Hurrah! My stepper motor has been running now for about 200 hours via this threads scenario.

        My particular application proved a bit more complicated as the module I'd been using was OO with a number of hashes, one of them quite large. And I find that the threads module gets kind of complicated if you try to OO-ify things. Still, not to worry. Quite easily gotten around, that.

        Most of that OO business was for non-stepper motor related issues: data and solenoid channels of the LabJack device. OO was by no means required for running the stepper channel as a separate consideration.

        So for the stepper motor I pared things back to essentials: just the basic (non-OO) module Device::LabJack. And that part only did I put into a thread with only the absolute minimum of shared scalars.

        Once simplifed in that manner it ran like a champ. The Tk GUI is lively again. Excellent suggestion. Thanks Zentara!

Re: How do I pass a reference to another program via @ARGV ???
by BrowserUk (Patriarch) on Dec 16, 2006 at 20:22 UTC

    The short answer to the title question is: You don't.

    A reference is effectively the address of a piece of memory in the address space of your perl process. When you start a new process, it cannot access that piece of memory in the originating process. Even if you passed the address to the new process and it attempted to dereference it, it would either a) segfault because the new process does not have that address in it's memory space, or b) it would access a piece of memory that holds some completely unrelated value.

    You could using one of the shared memory modules on CPAN, (eg. Win32::MMF ) but they tend to be fairly platform specific (ie. most don't work on win32), awkward to use and often very slow.

    Alternatively, you could consider using threads. Doing a Super Search for nodes containing threads Tk should throw up a few examples of using threads with Tk. But read them carefully, there are rules that must followed for that to be successful.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: How do I pass a reference to another program via @ARGV ???
by zentara (Archbishop) on Dec 16, 2006 at 22:09 UTC
Re: How do I pass a reference to another program via @ARGV ???
by jettero (Monsignor) on Dec 16, 2006 at 22:32 UTC
    Passing a "reference" between programs screams for the use of sockets (tcp, udp, unix, files, whatever) and the use of Storable for complicated structures or DB_File for simple values...

    -Paul

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://590225]
Approved by pKai
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2024-04-25 15:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found