Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Bidirectional Pipe Problem

Status
Not open for further replies.

cptk

Technical User
Mar 18, 2003
305
US
I have ...
set fid [open "|cprgm" "r+"]
fconfigure $fid -buffering line
.
.
.
puts $fid "1"
gets $fid c_return

Where cprgm is a C program that basically sits in an infinite loop, waits for input with the scanf cmd,
then takes the input and goes through a switch/case
cmd based on the value of the input.
The C program runs fine by itself (i.e. - standalone),
however when I run it with the above tcl code, it gives the following error:

Can't read "fid": no such variable.

When I look at the stack trace for error, it fails at the
puts line above.

Could it be it can't find the cprgm file (even though I've tried using the absolute path in the open cmd).
I'm stumped. Thanks for any help!!!!
 
Try to verify the braces balancing: if the braces mismatch the offending instruction can be out of the scope of the variable.

HTH

ulis
 
I don't see where the braces are off-balanced. Do you mean
within the tcl/tk script? If so, I'm pretty sure that's ok - in fact, I have these commands outside of any function/procedure. They reside at the global level, near the beginning. Could this be the problem?

Other notes: The problem, although I've stated occurs with the put cmd, it's actually with the set fid [open "|cprgm" "r+"] cmd. It doesn't seem recognize something in the open cmd.

To be safe, I did chmod the cprgm to 777.

 
Some more thoughts ...
Could the problem be:
1.) I have the r+ in quotes (i.e. - set fid [open "|cprgm" "r+"]
2.) I'm rusty on this, but since I defined the
cmds
set fid [open "|cprgm" "r+"]
fconfigure $fid -buffering line

outside any function, but I try to use the variable
fid

in a function, I need to define the fid
variable as
global in the function?
 
YES!
You have to add a
Code:
global fid
in the script of the proc and before any use of
Code:
fid
.

Alternatively you can use the :: notation for referencing fid:
Code:
fconfigure $::fid -buffering line
.

What happens is that the vars environment of a proc does'nt include the surrounding namespace env (the global one for you). This is different of the procs environment that includes the surrounding namespace env.

One more thing: the same occurs for the scripts in the callbacks (fileevent script for example). You don't have to worry with that if you don't 'code' in the script but only call a proc.

HTH

ulis
 
UPDATE ...

My problem, as I suspected, was that I didn't define the fileid as global in the proc. The issue of whether or not to quote the "r+" is a non-issue ... it doesn't matter.

But now I'm having buffering problems to work out ... I'm fflushing the stdout from the c program, but the front-end tcl script is only seeing one input line at a time -- I have many lines coming in from the c prgrm.
How do I loop the "gets" cmd efficently in the tcl script?
 
Code:
while {[gets $fd line] > -1} {
      #do stuff with $line
}
Works for me.
 
marsd: For some reason, the stmt
while {[gets $fd line] > -1} it's not working for me.

For example ...
Using a very simple tcl script, I click on a button in the tcl prgm, it executes a proc that sends a puts $fid "1" to c program. The c program, which waits for input, takes the value "1" via a switch cmd, and executes a printf line 3 times.

In the same proc as the "puts" cmd, I use the gets $fid retval cmd. By itself (without the gets in a while loop) the gets works fine. When I put three of these gets statements in succession, it works fine. When I put the forth gets line in, it obviuosly hangs (waiting for input).

Thus, when I try to use the gets in a while loop, it hangs. Anotherwords, it doesn't know to exit when there's no more data to read in.

What am I missing here????

 
Somehow eof is being missed.
I would strongly suspect the C program here or
your fconfigure options.

I'm on a windows machine today so my options are
limited but I created a working scenario with
source for comparison sake.

Code:
C CODE:

#include <stdlib.h>
#include <time.h>



#define iterations 12

void mysleep(int val);
char *randline(void);

int main(void) {
int xx = 0;

	 srand(time(NULL));
	 while (xx < iterations) {
		   mysleep(2);
		   printf(&quot;%s\n&quot;, randline());
		   fflush(stdout);
		   xx++;
     }
	 return 0;
}

void mysleep(int val) {
time_t start, current;

          time(&start);
		  current = (time_t)start + val;

		      while (start < current) {
				    time(&start);
			  }
}

char *randline(void) {
int p;
char *new = malloc(iterations * sizeof(char));

      for (p=0 ; p < iterations ; p++) {
		   new[p] = (char)(1 + rand() % 128);
	  }
	  return new;
}
TCL CODE
Code:
proc openprog {pname} {
      if {![file exists $pname]} {error &quot;Could not find $pname&quot;}
      set popen [open &quot;|$pname&quot; r]
      fconfigure $popen -buffering line
      while {[gets $popen line] > -1} {
              puts &quot;read from $popen: $line&quot;
      }
      catch {close $popen}
}

Output of openprog:

openprog c:/lcc/lcc1/slow_out.exe
read from fileb154e8: $'l.g.3
read from fileb154e8: }.1
read from fileb154e8: S.eZX6EvX/
read from fileb154e8: (qm&quot;uT!.P2)
read from fileb154e8: at$jF
read from fileb154e8: /w
read from fileb154e8: idj'v'$/z&quot;P
read from fileb154e8: Q{8p
read from fileb154e8: jsH-
read from fileb154e8: Bh:''~_:&quot;2_
read from fileb154e8: h;i~QOd'Do
read from fileb154e8: ]wku:16Y
read from fileb154e8: 5
read from fileb154e8: w!GMkBW9_x;
read from fileb154e8: ;W*p;4+S
read from fileb154e8: &quot;
read from fileb154e8: 8'xU?1?nv

HTH
 
I played around with some options and found that if I use
fconfigure $fid -blocking no,
it works.

By the way, the data coming in from the c program comes in via the following cmd:

fprintf(stdout, &quot;%d %s ...etc.&quot;, var1 var2 ...etc);
also, I do fflush(stdout); after each
fprintf cmd.

So, what's this no blocking doing for me? Can I get into trouble with this cmd?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top