Tcl_Ungets help [long, technical]?
- From: mghembru@xxxxxxxxxxxxxxxxxxxxxxx (MH)
- Date: Fri, 28 Apr 2006 00:35:39 +0000 (UTC)
Hi all.
Does anyone have experience using Tcl_Ungets, and mixing stdio and Tcl
streams?
Here's the scenario: we have a socket sending data. To avoid the "read and
resend" overhead, the Tcl app which is in control passes the Tcl channel to
my C++ extension to let it read and parse the data directly, and when the
data is done (ends with "." on a line by itself), my extension returns.
The controlling Tcl code (not mine, although I can poke around in it a bit)
then reads the socket with gets until it read a "." of its own (i.e. a
second ".").
Here's what the C++ code currently does (and it works) - I've omitted some
details for clarity:
Tcl_Channel ch = Tcl_GetChannel(interp, channel, &mode);
while( (len = Tcl_Gets(ch,&dstring)) >= 0 )
{
// do a little processing on the line
// process the object
processObject();
//needed to avoid appending
Tcl_DStringSetLength(&dstring,0);
}
Tcl_DStringFree(&dstring);
what I'd LIKE to do (I realize this is probably Unix specific - we'll deal
with Windows when we get to it):
Tcl_Channel ch = Tcl_GetChannel(interp, channel, &mode);
int fd, dfd;
if( Tcl_GetChannelHandle(ch, mode, (ClientData*) &fd) != TCL_OK)
{
//error
return;
}
dfd = dup(fd);
FILE *fp = fdopen(dfd, "r");
while( fgets(buff,10239, fp) != NULL )
{
// do a little processing on the line
// process the object
processObject();
}
That part works.
The problem is: due to buffering, etc. my dup-ed stream reads the second "."
from the socket, and when I return, there's no data for the Tcl app to
consume, so it blocks in its "gets".
So, in order to combat that, I've tried (after the second example above):
close(dfd);
idx = 0;
while( (c = fgets(fp)) != EOF )
{
buff[idx++] = c;
}
buff[idx]='\0';
fclose(fp);
printf("Channel bytes buffered: %d\n",Tcl_InputBuffered(ch));
c = Tcl_Ungets(ch,buff,idx,0);
printf("Channel bytes buffered: %d\n",Tcl_InputBuffered(ch));
printf("Start Reading\n");
while( (len = Tcl_Gets(ch,&dstring)) >= 0 )
{
printf("Read after bytes: %s\n",&dstring);
}
printf("Done Reading\n");
(the last little bit is to test the Ungets to see if it works).
I now get:
Channel bytes buffered: 0
Channel bytes buffered: 14
Start Reading
(and that's it).
I.e. MY code is now blocking in the Tcl_Gets.
However, I'm absolutely sure there are two \n's in the data. For good
measure, I translated \n to \r\n (Tcl seems to prefer this), and Tcl_Gets
still blocks. Even though there are two full lines to read, and
Tcl_InputBuffered tells me it got them.
So, obviously the "gets" in Tcl code after I return will also block. What am
I missing?
Thanks,
Mattias
.
- Follow-Ups:
- Prev by Date: Re: handling errors through catch
- Next by Date: How to export postscript from canvas?
- Previous by thread: bell boing scriipt quits
- Next by thread: Re: Tcl_Ungets help [long, technical]?
- Index(es):
Relevant Pages
|